How to peek inside a decorated function

Aaron Brady castironpi at gmail.com
Sun Feb 15 11:48:08 CET 2009


On Feb 15, 4:27 am, Hrvoje Niksic <hnik... at xemacs.org> wrote:
> Steven D'Aprano <st... at pearwood.info> writes:
> > Suppose I have a function f() which I know has been decorated, but I don't
> > have access to the original undecorated function any longer:
>
> > def reverse(func):
> >     def f(*args):
> >         args = list(args)
> >         args.reverse()
> >         return func(*args)
> >     return f
>
> > def say(*args):
> >     print args
>
> > rsay = reverse(say)
> > del say
>
> > Is there any way to peek inside the decorated function rsay() to get access
> > to the undecorated function say()?
>
> This works in Python 2.5.2:
>
> >>> rsay.func_closure[0].cell_contents
>
> <function say at 0xb7e67224>
>
> Of course, this applies only if you know there's only one free
> variable, and you know that the decorator is in fact implemented with
> a closure, and so on.
>
> >>>> dir(rsay.func_closure[0])
> > ['__class__', '__cmp__', '__delattr__', '__doc__',
> > '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
> > '__reduce_ex__', '__repr__', '__setattr__', '__str__']
>
> I got 'cell_contents' as well when I did the 'dir', at least under
> Python 2.5.2.

Assume the decorator preserves the function at all; that is, it
doesn't discard it.  Then you can scan func_closure.  In poor cases,
you might have to search through a nested decoration as well.  In
others, such as when the decorator is an object, not a function, you
might have to search an instance dictionary, also possibly nested.
The leading assumption also requires that the function is stored in a
Python object; that is, not in a C structure.

In Python 3.0.1:

>>> def f( fun ):
...     def g( *ar, **kw ):
...             return fun( *ar, **kw )
...     return g
...
>>> def h( x ):
...     print( x )
...
>>> i= f( h )
>>> i.__closure__[0].cell_contents
<function h at 0x00B59810>



More information about the Python-list mailing list