
Brett Cannon wrote:
A Signature object has the following structure attributes:
(1) Would this change with the new static __class__ attribute used for the new super? (2) What about functions without a name? Do you want to say str or NoneType, or is that assumed? (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?)
Is there a special key for the "->" returns annotation, or is that available as a separate property?
The structure of the Parameter object is:
What is used for unnamed arguments (typically provided by C)? I like None, but I see the arguments for both "" and missing attribute.
Is this just a property/alias for signature.parameters.index(self) ? What should a "parameter" object not associated with a specific signature return? -1, None, or missing attribute? 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.) ... 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.
When to construct the Signature object? ---------------------------------------
Since most code doesn't need it, I would expect it to be optimized out at least as often as docstrings are.
Why store it? Do you expect many use cases to need the signature more than once (but not to save it themselves)? If there is a __signature__ attribute on a object, you have to specify whether it can be replaced, which parts of it are writable, how that will affect the function's own behavior, etc. 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.
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.
Provide a mapping of parameter name to Parameter object? --------------------------------------------------------
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.
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.
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. -jJ

On 9/7/07, Jim Jewett <jimjjewett@gmail.com> wrote:
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>'.
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.
Oops, that didn't get into the PEP for some reason. The Signature object has ``has_annotation``/``annotation`` attributes for the 'return' annotation.
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.
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.
There is currently no way to work backwards from a Parameter object to its parent Signature. It could be added if people wanted.
What for? How does either have bearing on the call signature of a function?
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.
They are just snapshots unless people really want them to be live for some reason.
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.
I guess I can just try to do ``item.__index__()`` and if that triggers an AttributeError assume it is a name.
You can also just use hasattr() if needed.
So another vote for None. Thanks for the feedback, Jim!

On 9/7/07, Brett Cannon <brett@python.org> wrote:
I don't think it'll work -- the __class__ variable is only available *within* the function, not when one is introspecting the function object. Also, it is only available for functions that reference 'super' (or __class__ directly). As __class__ is passed into the function call as a "cell" variable (like references to variables from outer scopes), its mere presense slows down the call somewhat, hence it is only present when used. (BTW, it is not an attribute.) BTW there's a good reason why functions don't have easier access to the class in which they are defined: functions can easily be moved or shared between classes. The __class__ variable only records the class inside which the function is defined lexically, if any. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On 9/7/07, Jim Jewett <jimjjewett@gmail.com> wrote:
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>'.
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.
Oops, that didn't get into the PEP for some reason. The Signature object has ``has_annotation``/``annotation`` attributes for the 'return' annotation.
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.
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.
There is currently no way to work backwards from a Parameter object to its parent Signature. It could be added if people wanted.
What for? How does either have bearing on the call signature of a function?
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.
They are just snapshots unless people really want them to be live for some reason.
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.
I guess I can just try to do ``item.__index__()`` and if that triggers an AttributeError assume it is a name.
You can also just use hasattr() if needed.
So another vote for None. Thanks for the feedback, Jim!

On 9/7/07, Brett Cannon <brett@python.org> wrote:
I don't think it'll work -- the __class__ variable is only available *within* the function, not when one is introspecting the function object. Also, it is only available for functions that reference 'super' (or __class__ directly). As __class__ is passed into the function call as a "cell" variable (like references to variables from outer scopes), its mere presense slows down the call somewhat, hence it is only present when used. (BTW, it is not an attribute.) BTW there's a good reason why functions don't have easier access to the class in which they are defined: functions can easily be moved or shared between classes. The __class__ variable only records the class inside which the function is defined lexically, if any. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (3)
-
Brett Cannon
-
Guido van Rossum
-
Jim Jewett