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

Brett Cannon brett at python.org
Tue May 2 20:43:56 CEST 2006


On 5/2/06, Nick Coghlan <ncoghlan at gmail.com> wrote:

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)".

It does for decorators. How do you make sure that a decorator uses the signature object of the wrapped function instead of the decorator? Or are you saying to just not worry about that right now?

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 :)

Thanks, Nick!

-Brett

Cheers, Nick.

def bind(*args, **kwds): """Return a dict mapping parameter names to bound arguments""" self = args[0] args = args[1:] boundparams = {} numargs = len(args) missingargs = set(self.requiredargs) argnames = self.requiredargs + self.optionalargs numnames = len(argnames) # Handle excess positional arguments if self.extraargs: boundparams[self.extraargs] = tuple(args[numnames:]) elif numargs > numnames: self.raiseargserror(numargs) # Bind positional arguments for name, value in zip(argnames, args): boundparams[name] = value missingargs -= set((name,)) # Bind keyword arguments (and handle excess) if self.extrakwds: extrakwds = dict() boundparams[self.extrakwds] = extrakwds else: extrakwds = None for name, value in kwds.items(): if name in boundparams: raise TypeError( "Got multiple values for argument '%s'" % name) elif name in argnames: missingargs -= set((name,)) boundparams[name] = value elif extrakwds is not None: extrakwds[name] = value else: raise TypeError( "Got unexpected keyword argument '%s'" % name) if missingargs: self.raiseargserror(numargs) # All done return boundparams

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



More information about the Python-Dev mailing list