how to check if a function signature "matches" without calling the function?

Alex Martelli aleax at aleax.it
Wed Sep 25 05:47:08 EDT 2002


Mike McCandless wrote:

> Does Python 2.2.1 make it possible for me to see some details about
> the expected arguments that a function takes, without actually calling
> the function?

Yes.  inspect.getargspec lets you learn all you need:

import inspect
argnames, has_varargs, has_kdws, default_values = inspect.getargspec(func)


> Specifically, if I have a function or method object, and I have a
> tuple + dict of arguments I'd like to apply it on, is there a function
> I can call that would check if the tuple + dict can be properly
> "coerced" to the formal parameters?

You still have some work to do for your checking, but it doesn't
seem to be much.  You need to check you supply each mandatory
argument exactly once, and each optional argument 0 or 1 time;
you can have other positional args only if has_varargs, and
other named args only if has_kwds.  E.g. for clarity:


class NoWay(Exception): pass

def times_supplied(argname, argposition, atuple, adict):
    return (argname in adict) + (argposition < len(atuple))

def check_args(argnames, default_values, atuple, adict):

    number_mandatory = len(argnames) - len(default_values)

    for pos in range(len(argnames)):
        name = argnames[pos]
        n = times_supplied(name, pos, atuple, adict)
        if n<1 and pos<number_mandatory:
            raise NoWay, "Mandatory argument %s (%s) missing" % (name, pos)
        elif n>1:
            raise NoWay, "Argument %s (%s) given twice" % (name, pos)

def check_funcargs(func, atuple, adict):
    import inspect
    names, has_varargs, has_kdws, defaults = inspect.getargspec(func)
    check_args(names, defaults, atuple, adict)
    if not has_varargs and len(atuple)>len(names):
        raise NoWay, "Supplied %d positional args, max is %d" % (
            len(atuple), len(names) )
    if not has_kwds:
        for name in adict:
            if name not in names:
                raise NoWay, "Unknown argument %s" % name


You can express this more concisely &c, of course, or use other
means than raising a dedicated exception to diagnose problems
(I only diagnose the first problem if any, that can be tweaked
too, of course).


Alex




More information about the Python-list mailing list