[Python-Dev] signature object issues (to discuss while I am out of contact)

Nick Coghlan ncoghlan at gmail.com
Tue May 2 13:04:06 CEST 2006


Brett Cannon wrote:
> One is whether a signature object should be automatically created for
> every function.  As of right now the PEP I am drafting has it on a
> per-need basis and have it assigned to __signature__ through a
> built-in function or putting it 'inspect'.  Now automatically creating
> the object would possibly make it more useful, but it could also be
> considered overkill.  Also not doing it automatically allows signature
> objects to possibly make more sense for classes (to represent
> __init__) and instances (to represent __call__).  But having that same
> support automatically feels off for some reason to me.

My current impulse is to put the signature object in the inspect module to 
start with, and don't give it a special attribute at all.

All of the use cases I can think of (introspection for documentation purposes 
or argument checking purposes) don't really suffer either way regardless of 
whether the signature retrieval is spelt "obj.__signature__" or 
"inspect.getsignature(obj)".

Since it doesn't make much difference from a usability point of view, let's 
start with the object in the library module first.

> The second question is whether it is worth providing a function that
> will either figure out if a tuple and dict representing arguments
> would work in calling the function.  Some have even suggested a
> function that returns the actual bindings if the call were to occur. 
> Personally I don't see a huge use for either, but even less for the
> latter version.  If people have a legit use case for either please
> speak up, otherwise I am tempted to keep the object simple.

A "bind" method on the signature objects is pretty much essential for any kind 
of argument checking usage.

In addition to Aahz's precondition checking example, Talin gave a good example 
on the Py3k list of a function decorator for logging all calls to a function, 
and including the argument bindings in the log message.

And just in case you think the operation would be easy to implement if you 
need it, I've included below the bind method from the signature object I wrote 
to play around with the ideas posted to the Py3k list. It took a fair bit of 
work to get it to spit out the right answers :)

Cheers,
Nick.

     def bind(*args, **kwds):
         """Return a dict mapping parameter names to bound arguments"""
         self = args[0]
         args = args[1:]
         bound_params = {}
         num_args = len(args)
         missing_args = set(self.required_args)
         arg_names = self.required_args + self.optional_args
         num_names = len(arg_names)
         # Handle excess positional arguments
         if self.extra_args:
             bound_params[self.extra_args] = tuple(args[num_names:])
         elif num_args > num_names:
             self._raise_args_error(num_args)
         # Bind positional arguments
         for name, value in zip(arg_names, args):
             bound_params[name] = value
             missing_args -= set((name,))
         # Bind keyword arguments (and handle excess)
         if self.extra_kwds:
             extra_kwds = dict()
             bound_params[self.extra_kwds] = extra_kwds
         else:
             extra_kwds = None
         for name, value in kwds.items():
             if name in bound_params:
                 raise TypeError(
                     "Got multiple values for argument '%s'" % name)
             elif name in arg_names:
                 missing_args -= set((name,))
                 bound_params[name] = value
             elif extra_kwds is not None:
                 extra_kwds[name] = value
             else:
                 raise TypeError(
                     "Got unexpected keyword argument '%s'" % name)
         if missing_args:
             self._raise_args_error(num_args)
         # All done
         return bound_params


-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-Dev mailing list