On Wed, Jun 6, 2012 at 10:10 PM, Yury Selivanov <yselivanov...@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...@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 _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com