decorating functions with generic signatures (not for the faint of heart)

Michele Simionato michele.simionato at gmail.com
Fri Apr 8 06:54:39 EDT 2005


I said it was very little tested! ;)

This should work better:

#<decorate.py>

def _signature_gen(varnames, n_default_args, n_args,
rm_defaults=False):
    n_non_default_args = n_args - n_default_args
    non_default_names = varnames[:n_non_default_args]
    default_names = varnames[n_non_default_args:n_args]
    other_names = varnames[n_args:]
    n_other_names = len(other_names)
    for name in non_default_names:
        yield "%s" % name
    for i, name in enumerate(default_names):
        if rm_defaults:
            yield name
        else:
            yield "%s = arg[%s]" % (name, i)
    if n_other_names == 1:
        yield "*%s" % other_names[0]
    elif n_other_names == 2:
        yield "*%s" % other_names[0]
        yield "**%s" % other_names[1]

def decorate(func, caller):
    argdefs = func.func_defaults or ()
    argcount = func.func_code.co_argcount
    varnames = func.func_code.co_varnames
    signature = ", ".join(_signature_gen(varnames, len(argdefs),
argcount))
    variables = ", ".join(_signature_gen(varnames, len(argdefs),
argcount,
                                        rm_defaults=True))
    lambda_src = "lambda %s: call(func, %s)" % (signature, variables)
    dec_func = eval(lambda_src, dict(func=func, call=caller,
arg=argdefs))
    dec_func.__name__ = func.__name__
    dec_func.__doc__ = func.__doc__
    dec_func.__dict__ = func.__dict__.copy()
    return dec_func

#</decorate.py>




More information about the Python-list mailing list