How to peek inside a decorated function
Peter Otten
__peter__ at web.de
Sun Feb 15 04:05:32 EST 2009
Steven D'Aprano wrote:
> 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()?
>
> If I look at the code object I can see a reference to the original:
>
>>>> rsay.func_code.co_names
> ('list', 'args', 'reverse', 'func')
>
> and if I disassemble the code object I can see it being dereferenced:
>
>>>> dis.dis(rsay.func_code)
> [snip for brevity]
> 5 22 LOAD_DEREF 0 (func)
> 25 LOAD_FAST 0 (args)
> 28 CALL_FUNCTION_VAR 0
> 31 RETURN_VALUE
>
> but if I look at the closure object, nothing seems useful:
>
>>>> dir(rsay.func_closure[0])
> ['__class__', '__cmp__', '__delattr__', '__doc__',
> '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
> '__reduce_ex__', '__repr__', '__setattr__', '__str__']
>
>
> and I can't find any other attributes which refers back to the undecorated
> original function.
>
>
Following Terry's lead it turns out that cell contents become easily
accessible in python 2.5:
$ cat cellcontents.py
"""
>>> 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
>>> c = rsay.func_closure[0]
>>> "cell_contents" in dir(c)
True
>>> c.cell_contents(1,2,3)
(1, 2, 3)
>>>
"""
import doctest
doctest.testmod()
$ python2.6 cellcontents.py
$ python2.5 cellcontents.py
$ python2.4 cellcontents.py
**********************************************************************
File "cellcontents.py", line 15, in __main__
Failed example:
"cell_contents" in dir(c)
Expected:
True
Got:
False
**********************************************************************
File "cellcontents.py", line 17, in __main__
Failed example:
c.cell_contents(1,2,3)
Exception raised:
Traceback (most recent call last):
File "doctest.py", line 1248, in __run
compileflags, 1) in test.globs
File "<doctest __main__[6]>", line 1, in ?
c.cell_contents(1,2,3)
AttributeError: 'cell' object has no attribute 'cell_contents'
**********************************************************************
1 items had failures:
2 of 7 in __main__
***Test Failed*** 2 failures.
Peter
More information about the Python-list
mailing list