[Python-Dev] PEP 362: Signature objects (original) (raw)
Brett Cannon brett at python.org
Sat Sep 8 02:59:35 CEST 2007
- Previous message: [Python-Dev] PEP 362: Signature objects
- Next message: [Python-Dev] PEP 362: Signature objects
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 9/7/07, Jim Jewett <jimjjewett at gmail.com> 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 ''.
(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.
> * varannotations: 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
varargs
andvarkwargs
default toNone
?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!
- Previous message: [Python-Dev] PEP 362: Signature objects
- Next message: [Python-Dev] PEP 362: Signature objects
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]