[Python-Dev] Updated PEP 362 (Function Signature Object)

Daniel Urban urban.dani+py at gmail.com
Thu Jun 7 06:44:56 CEST 2012


On Wed, Jun 6, 2012 at 10:10 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> On 2012-06-06, at 3:33 PM, Daniel Urban wrote:
>> 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?
>
> You're missing the point.  BoundArguments contains properly mapped
> *args and **kwargs passed to Signature.bind.  You can validate them after,
> do type casts, modify them, overwrite etc. by manipulating
> 'BoundArguments.arguments'.
>
> At the end you can't, however, invoke the function by doing:
>
>   func(**bound_arguments.arguments) # <- this won't work
>
> as varargs will be screwed.
>
> That's why you need 'args' & 'kwargs' properties on BoundArguments.
>
> Imagine, that "Annotation Checker" example is modified to coerce all string
> arguments to int (those that had 'int' in annotation) and then to multiply
> them by 42.
>
> We'd write the following code:
>
>   for arg_name, arg_value in bound_arguments.arguments.items():
>      # I'm skipping is_args & is_kwargs checks, and assuming
>      # we have annotations everywhere
>      if sig.parameters[arg_name].annotation is int \
>                                and isinstance(arg_value, str):
>          bound_arguments.arguments[arg_name] = int(arg_value) * 42
>
>   return func(*bound_arguments.args, **bound_arguments.kwargs)

I see. Thanks, this modifying example is the first convincing use case
I hear. Maybe it would be good to mention something like this in the
PEP.


Daniel


More information about the Python-Dev mailing list