Greetings, List!

The recent thread about a recursive function in a class definition led me back to a post about bindfunc from Arnaud, and from there I found Michele Simionato's decorator module (many thanks! :-), and from there I began to wonder...

from decorator import decorator

@decorator
def recursive1(func, *args, **kwargs):
    return func(func, *args, **kwargs)

@recursive1
def factorial1(recurse, n):
    if n < 2:
        return 1
    return n * recurse(n-1)

factorial(4)
TypeError: factorial1() takes exactly 2 arguments (1 given)

Now it's *entirely* possible that I am missing something easy here, but at any rate I was thinking about the above error, about how one of the design goals behind the decorator module was to enable introspection to give accurate information about usage, etc, and how if the signature was *exactly* preserved then we have this pesky and seemingly out of place variable, not mention we can't 'just use it' in the code.

So I set out to create a signature-modifying decorator that would lose that first parameter from the wrapper, while keeping the rest of the signature intact. This is what I was able to come up with:

def recursive(func):
    """
    recursive is a signature modifying decorator.
    Specifially, it removes the first argument, so
    that calls to the decorated function act as
    if it does not exist.
    """
    argspec = inspect.getargspec(func)
    first_arg = argspec[0][0]
    newargspec = (argspec[0][1:], ) + argspec[1:]
    fi = decorator.FunctionMaker(func)
    old_sig = inspect.formatargspec( \
        formatvalue=lambda val: "", *argspec)[1:-1]
    new_sig = inspect.formatargspec( \
        formatvalue=lambda val: "", *newargspec)[1:-1]
    new_def = '%s(%s)' % (fi.name, new_sig)
    body = 'return func(%s)' % old_sig
    def wrapper(*newargspec):
        return func(wrapper, *newargspec)
    evaldict = {'func':func, first_arg:wrapper}
    return fi.create(new_def, body, evaldict, \
        doc=fi.doc, module=fi.module)


I cannot remember whose sig it is at the moment (maybe Aahz'?), but it says something about debugging being twice as hard as coding, so if you code as cleverly as you can you are, by definition, not smart enough to debug it! And considering the amount of trial-and-error that went into this (along with some thought and reasoning about scopes !-), I am hoping to get some code review.

And if there's an easier way to do this, I wouldn't mind knowing about that, too!

Many thanks.

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to