[Python-Dev] Updated PEP 362 (Function Signature Object)
Daniel Urban
urban.dani+py at gmail.com
Wed Jun 6 21:33:31 CEST 2012
On Wed, Jun 6, 2012 at 8:35 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> On 2012-06-06, at 2:22 PM, Daniel Urban wrote:
>>> I'll try to answer you with the following code:
>>>
>>> >>> def foo(*args):
>>> ... print(args)
>>>
>>> >>> bound_args = signature(foo).bind(1, 2, 3)
>>> >>> bound_args.arguments
>>> OrderedDict([('args', (1, 2, 3))])
>>>
>>> You can't invoke 'foo' by:
>>>
>>> >>> foo(**bound_args.arguments)
>>> TypeError: foo() got an unexpected keyword argument 'args'
>>
>> Of course, but you can invoke it with "1, 2, 3", the arguments you
>> used to create the BoundArguments instance in the first place: foo(1,
>> 2, 3) will work fine.
>
> The whole point is to use BoundArguments mapping for invocation.
> See Nick's idea to validate callbacks, and my response to him, below in
> the thread.
>
>>> That's why we have two dynamic properties 'args', and 'kwargs':
>>
>> Ok, but what I'm saying is, that we don't really need them.
>
> We need them. Again, in some contexts you don't have the arguments
> you've passed to bind().
But how could we *need* bind to return 'args' and 'kwargs' to us, when
we wouldn't be able to call bind in the first place, if we wouldn't
had the arguments?
>>> >>> bound_args.args, bound_args.kwargs
>>> ((1, 2, 3), {})
>>>
>>> 'BoundArguments.arguments', as told in the PEP, is a mapping to work
>>> with 'Signature.parameters' (you should've seen it in the
>>> "Annotation Checker" example).
>>>
>>> 'args' & 'kwargs' are for invocation. You can even modify 'arguments'.
>>>
>>>>> Has the following public attributes:
>>>>>
>>>>> * arguments : OrderedDict
>>>>> An ordered mutable mapping of parameters' names to arguments' values.
>>>>> Does not contain arguments' default values.
>>>>
>>>> Does this mean, that if the arguments passed to bind doesn't contain a
>>>> value for an argument that has a default value, then the returned
>>>> mapping won't contain that argument? If so, why not?
>>>> inspect.getcallargs works fine with default values.
>>>
>>> Yes, it won't. It contains only arguments you've passed to the 'bind'.
>>> The reason is because we'd like to save as much of actual context as
>>> possible.
>>
>> I don't really see, where this "context" can be useful. Maybe an
>> example would help.
>
> For instance, for some sort of RPC mechanism, where you don't need to
> store/pass arguments that have default values.
I see. So, basically, it's an optimization.
>>> If you pass some set of arguments to the bind() method, it tries to map
>>> precisely that set. This way you can deduce from the BoundArguments what
>>> it was bound with. And default values will applied by python itself.
>>
>> Anyway, I think it would be nice to be able to obtain the full
>> arguments mapping that the function would see, not just a subset. Of
>> course, we can use inspect.getcallargs for that, but I think we should
>> be able to do that with the new Signature API.
>
>
> Well, it will take just a few lines of code to enrich BoundArguments with
> default values (we can add a method to do it, if it's really that required
> feature). But you won't be able to ever reconstruct what arguments the
> bind() method was called with, if we write default values to arguments
> from start.
As I've mentioned above, I don't think, we have to be able to
reconstruct the arguments passed to bind from the return value of
bind. If we will need the original arguments later/in another place,
we will just save them, bind doesn't have to complicate its API with
them.
> Also, it's better for performance. "Annotation Checker" example does
> defaults validation first, and never checks them again. If bind() would
> write default values to 'BoundArguments.arguments', you would check
> defaults on each call. And think about more complicated cases, where
> processing of argument's value is more complicated and time consuming.
Ok, so again, it is an optimization.
Daniel
More information about the Python-Dev
mailing list