在下面的代码中,func2
似乎__globals__
func1
+还有来自contextlib
的符号。任何人都可以详细说明这个globals
合并是如何工作的吗? IE,它是否合并了__dict__
所有涉及定义函数的模块?此外,当名称冲突时会发生什么?
import contextlib
def func1():
pass
@contextlib.contextmanager
def func2(args):
pass
globals1 = set(func1.__globals__.keys())
globals2 = set(func2.__globals__.keys())
globals2.difference(globals1)
{'GeneratorContextManager',
'__all__',
'__file__',
'closing',
'contextmanager',
'nested',
'warn',
'wraps'}
使用Python 2.7.10
答案 0 :(得分:3)
每个函数对象都有__globals__
给出对定义函数的模块的全局命名空间的引用。
在您的示例中,func1
在您的模块中定义,并具有该模块的全局变量。您在模块中定义了func2
,但contextmanager
装饰器用另一个函数包装了您的函数。该包装函数在contextlib
中定义,因此当装饰器用包装版本替换func2
时,生成的函数具有contextlib
的全局变量。它不具有模块的全局变量。
但是,包装函数会保留对原始函数的引用,该函数仍然具有您自己模块的全局变量。在您的示例中,可以通过func2.__closure__[0].cell_contents
:
# func1 is not in func2's globals
>>> func2.__globals__['func1']
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
func2.__globals__['func1']
KeyError: u'func1'
# func1 is in the globals of the internally-stored wrapped version of func2
>>> func2.__closure__[0].cell_contents.__globals__['func1']
<function func1 at 0x0000000002B2B358>