On 9/7/07, Jim Jewett <[EMAIL PROTECTED]> wrote:
> > A Signature object has the following structure attributes:
>
> > * name : str
> > Name of the function. This is not fully qualified because
> > function objects for methods do not know the class they are
> > contained within. This makes functions and methods
> > indistinguishable from one another when passed to decorators,
> > preventing proper creation of a fully qualified name.
>
> (1) Would this change with the new static __class__ attribute used
> for the new super?
>
I don't know enough about the super implementation to know. If you
can figure out the class from the function object alone then sure,
this can change.
> (2) What about functions without a name? Do you want to say str or
> NoneType, or is that assumed?
>
What functions don't have a name? Even lambdas have the name '<lambda>'.
> (3) Is the Signature object live or frozen? (name is writable ...
> will the Signature object reflect the new name, or the name in use at
> the time it was created?)
>
They are currently one-time creation objects. One could change it to
use properties and do the look up dynamically by caching the function
object. But I currently have it implemented as all created in
__init__ and then just left alone.
> > * var_annotations: dict(str, object)
> > Dict that contains the annotations for the variable parameters.
> > The keys are of the variable parameter with values of the
>
> Is there a special key for the "->" returns annotation, or is that
> available as a separate property?
>
Oops, that didn't get into the PEP for some reason. The Signature
object has ``has_annotation``/``annotation`` attributes for the
'return' annotation.
> > The structure of the Parameter object is:
>
> > * name : (str | tuple(str))
> > The name of the parameter as a string if it is not a tuple. If
> > the argument is a tuple then a tuple of strings is used.
>
> What is used for unnamed arguments (typically provide by C)? I like
> None, but I see the arguments for both "" and missing attribute.
>
It's open for debate. I didn't even think about functions not having
__name__ set. Basically whatever people want to go with for var_args
and var_kw_args.
> > * position : int
> > The position of the parameter within the signature of the
> > function (zero-indexed). For keyword-only parameters the position
> > value is arbitrary while not conflicting with positional
> > parameters.
>
> Is this just a property/alias for signature.parameters.index(self) ?
>
Assuming that 'self' refers to some parameter, yes.
> What should a "parameter" object not associated with a specific
> signature return? -1, None, or missing attribute?
>
This is not an option as it must be specified by the Parameter
constructor. A Parameter object should not exist without belonging to
a Signature object. That's why neither Signature nor Parameter have
their constructors specified; the signature() function is the only way
you should cause the construction of either object.
> Is there a way to get the associated Signature, or is it "compiled
> out" when the Signature and its child Parameters are first
> constructed? (I think the position property is the only attribute
> that would use it, unless you want some of the other attributes --
> like annotations -- to be live.)
There is currently no way to work backwards from a Parameter object to
its parent Signature. It could be added if people wanted.
>
> ...
>
> I would also like to see a
>
> * value : object
>
> attribute; this would be missing on most functions, but might be
> filled in on a Signature representing a closure, or an execution
> frame.
What for? How does either have bearing on the call signature of a function?
>
>
> > When to construct the Signature object?
> > ---------------------------------------
>
> > The Signature object can either be created in an eager or lazy
> > fashion. In the eager situation, the object can be created during
> > creation of the function object.
>
> Since most code doesn't need it, I would expect it to be optimized out
> at least as often as docstrings are.
>
> > In the lazy situation, one would
> > pass a function object to a function and that would generate the
> > Signature object and store it to ``__signature__`` if
> > needed, and then return the value of ``__signature__``.
>
> Why store it? Do you expect many use cases to need the signature more
> than once (but not to save it themselves)?
Because you can use these with decorators to allow introspection redirection::
def dec(fxn):
def inner(*args, **kwargs):
return fxn(*args, **kwargs)
sig = signature(fxn)
inner.__signature__ = sig
return inner
>
> If there is a __signature__ attribute on a object, you have to specify
> whether it can be replaced,
It can.
> which parts of it are writable,
Any of it.
> how that
> will affect the function's own behavior, etc.
It won't.
> I also suspect it might
> become a source of heisenbugs, like the "reference leaks" that were
> really DUMMY items in a dict.
>
> If the Signature is just a snapshot no longer attached to the original
> function, then people won't expect changes to the Signature to affect
> the callable.
>
They are just snapshots unless people really want them to be live for
some reason.
> > Should ``Signature.bind`` return Parameter objects as keys?
>
> (see above) If a Signature is a snapshot (rather than a live part of
> the function), then it might make more sense to just add a value
> attribute to Parameter objects.
>
Why? You might make several calls to bind() and thus setting what a
Parameter object would be bound to should be considered a temporary
thing.
> > Provide a mapping of parameter name to Parameter object?
> > --------------------------------------------------------
>
> > While providing access to the parameters in order is handy, it might
> > also be beneficial to provide a way to retrieve Parameter objects from
> > a Signature object based on the parameter's name. Which style of
> > access (sequential/iteration or mapping) will influence how the
> > parameters are stored internally and whether __getitem__ accepts
> > strings or integers.
>
> I think it should accept both.
>
> What storage mechanism to use is an internal detail that should be
> left to the implementation. I wouldn't expect Signature inspection to
> be inside a tight loop anyhow, unless it were part of a Generic
> Function dispatch engine ... and those authors (just PJE?) can
> optimize on what they actually need.
>
I guess I can just try to do ``item.__index__()`` and if that triggers
an AttributeError assume it is a name.
> > Remove ``has_*`` attributes?
> > ----------------------------
>
> > If an EAFP approach to the API is taken,
>
> Please leave them; it is difficult to catch Exceptions in a list
> comprehension.
>
You can also just use hasattr() if needed.
> > Have ``var_args`` and ``_var_kw_args`` default to ``None``?
>
> Makes sense to me, particularly since it should probably be consistent
> with function name, and that should probably be None.
So another vote for None.
Thanks for the feedback, Jim!
_______________________________________________
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com