recursive decorator

Ethan Furman ethan at stoneleaf.us
Tue Sep 8 19:01:49 EDT 2009


Michele Simionato wrote:
[snip]
> Yes, it is portable. BTW, here is what you want to do (requires
> decorator-3.1.2):
> 
> from decorator import FunctionMaker
> 
> def bindfunc(f):
>     name = f.__name__
>     signature = ', '.join(FunctionMaker(f).args[1:]) # skip first arg
>     return FunctionMaker.create(
>         '%s(%s)' % (name,  signature),
>         'return _func_(%s, %s)' % (name, signature),
>         dict(_func_=f), defaults=f.func_defaults,
>                doc=f.__doc__, module=f.__module__)

I figured there must be an easy way using your module.  Here is what I 
came up with *not* using the module -- this whole thing was definitely a 
mind-stretching exercise.  Many thanks for your decorator routines -- no 
way could I have gotten this far without them to guide me!

def bind_func(func):
     name = func.__name__
     argspec = inspect.getargspec(func)
     self = argspec[0][0]
     newargspec = (argspec[0][1:], ) + argspec[1:]
     signature = inspect.formatargspec( \
       formatvalue=lambda val: "", *newargspec)[1:-1]
     new_func = 'def _wrapper_(%(signature)s):\n' \
                '    return %(self)s(_wrapper_, %(signature)s)' % \
                {'signature':signature, 'self':'old_func'}
     evaldict = {'old_func':func}
     exec new_func in evaldict
     wrapped = evaldict['_wrapper_']
     wrapped.__name__ = name
     wrapped.__doc__ = func.__doc__
     wrapped.__module__ = func.__module__
     wrapped.__dict__ = func.__dict__
     wrapped.func_defaults = func.func_defaults
     return wrapped

~Ethan~



More information about the Python-list mailing list