" __全局__"在使用装饰器时合并?

时间:2016-05-23 01:15:39

标签: python

在下面的代码中,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

1 个答案:

答案 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>