J
John Nagle
I'm doing something with CPython introspection, and I'm trying
to determine whether a function is a closure. Consider
def foo(x) :
global fbar
def bar(y) :
pass
fbar = bar # export closure
foo(0)
We now have "fbar" as a reference to a closure.
"inspect" can tell us some things about foo and fbar:
No difference there.
{'fbar': <function bar at 0x021FD470>,
'__builtins__': <module '__builtin__' (built-in)>,
'inspect': <module 'inspect' from 'C:\python26\lib\inspect.pyc'>,
'm':
[('__call__', <method-wrapper '__call__' of function object at 0x021FD470>),
('__class__', <type 'function'>), ('__closure__', None),
('__code__', <code object bar at 021F1C38, file "<stdin>", line 3>),
('__defaults__', None),
('__delattr__', <method-wrapper '__delattr__' of function object at
0x021FD470>),
('__dict__', {}),
('__doc__', None), ('__format__', <built-in method __format__ of
function object at 0x021FD470>),
('__get__', <method-wrapper '__get__' of function object at 0x021FD470>),
('__getattribute__', <method-wrapper '__getattribute__' of function
object at 0x021FD470>),
('__globals__', {...}),
('__hash__', <method-wrapper '__hash__' of function object at 0x021FD470>),
('__init__', <method-wrapper '__init__' of function object at 0x021FD470>),
('__module__', '__main__'),
('__name__', 'bar'),
('__new__', <built-in method __new__ of type object at 0x1E1FACF0>),
('__reduce__', <built-in method __reduce__ of function object at
0x021FD470>),
('__reduce_ex__', <built-in method __reduce_ex__ of function object at
0x021FD470>),
('__repr__', <method-wrapper '__repr__' of function object at 0x021FD470>),
('__setattr__', <method-wrapper '__setattr__' of function object at
0x021FD470>),
('__sizeof__', <built-in method __sizeof__ of function object at
0x021FD470>),
('__str__', <method-wrapper '__str__' of function object at 0x021FD470>),
('__subclasshook__', <built-in method __subclasshook__ of type object at
0x1E1FACF0>),
('func_closure', None),
('func_code', <code object bar at 021F1C38, file "<stdin>", line 3>),
('func_defaults', None),
('func_dict', {}),
('func_doc', None),
('func_globals', {...}),
('func_name', 'bar')],
'__package__': None, '__name__': '__main__',
No indication there that "fbar" is a closure inside "foo". There
are "__closure__" and "__func_closure__" entries in there, but
they are both None. A non-closure function has the same entries.
So how can I detect a closure?
John Nagle
to determine whether a function is a closure. Consider
def foo(x) :
global fbar
def bar(y) :
pass
fbar = bar # export closure
foo(0)
We now have "fbar" as a reference to a closure.
"inspect" can tell us some things about foo and fbar:
ArgSpec(args=['y'], varargs=None, keywords=None, defaults=None)>>> inspect.getargspec(foo) ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
>>> inspect.getargspec(fbar)
No difference there.
{'fbar': <function bar at 0x021FD470>,
'__builtins__': <module '__builtin__' (built-in)>,
'inspect': <module 'inspect' from 'C:\python26\lib\inspect.pyc'>,
'm':
[('__call__', <method-wrapper '__call__' of function object at 0x021FD470>),
('__class__', <type 'function'>), ('__closure__', None),
('__code__', <code object bar at 021F1C38, file "<stdin>", line 3>),
('__defaults__', None),
('__delattr__', <method-wrapper '__delattr__' of function object at
0x021FD470>),
('__dict__', {}),
('__doc__', None), ('__format__', <built-in method __format__ of
function object at 0x021FD470>),
('__get__', <method-wrapper '__get__' of function object at 0x021FD470>),
('__getattribute__', <method-wrapper '__getattribute__' of function
object at 0x021FD470>),
('__globals__', {...}),
('__hash__', <method-wrapper '__hash__' of function object at 0x021FD470>),
('__init__', <method-wrapper '__init__' of function object at 0x021FD470>),
('__module__', '__main__'),
('__name__', 'bar'),
('__new__', <built-in method __new__ of type object at 0x1E1FACF0>),
('__reduce__', <built-in method __reduce__ of function object at
0x021FD470>),
('__reduce_ex__', <built-in method __reduce_ex__ of function object at
0x021FD470>),
('__repr__', <method-wrapper '__repr__' of function object at 0x021FD470>),
('__setattr__', <method-wrapper '__setattr__' of function object at
0x021FD470>),
('__sizeof__', <built-in method __sizeof__ of function object at
0x021FD470>),
('__str__', <method-wrapper '__str__' of function object at 0x021FD470>),
('__subclasshook__', <built-in method __subclasshook__ of type object at
0x1E1FACF0>),
('func_closure', None),
('func_code', <code object bar at 021F1C38, file "<stdin>", line 3>),
('func_defaults', None),
('func_dict', {}),
('func_doc', None),
('func_globals', {...}),
('func_name', 'bar')],
'__package__': None, '__name__': '__main__',
No indication there that "fbar" is a closure inside "foo". There
are "__closure__" and "__func_closure__" entries in there, but
they are both None. A non-closure function has the same entries.
So how can I detect a closure?
John Nagle