类范围中的闭包

geo*_*org 5 python scope class

根据我的理解,函数和类范围的行为几乎相同:

>>> def x():
...     a = 123
...     print (locals())
... 
>>> x()
{'a': 123}


>>> class x():
...     a = 123
...     print (locals())
... 
{'a': 123, '__module__': '__main__'}
Run Code Online (Sandbox Code Playgroud)

但是,当我定义一个闭包时,行为是不同的.函数只是返回本地绑定,如预期的那样:

>>> def x():
...     a = 123
...     t = lambda: a
...     return t
... 
>>> x()()
123
Run Code Online (Sandbox Code Playgroud)

而在一个类中,绑定似乎丢失了:

>>> class x():
...     a = 123
...     t = lambda self: a
... 
>>> x().t()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in <lambda>
NameError: global name 'a' is not defined
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释这种差异吗?

Mar*_*ers 4

类作用域是一个临时作用域,它仅在执行类定义主体时存在。结果dict用于创建类的命名空间,即__dict__类的 。

\n\n

就类中定义的函数而言,下一个作用域是class定义本身的作用域。

\n\n

以下工作正常:

\n\n
>>> def foo():\n...     spam = \'eggs\'\n...     class Bar(object):\n...         def baz(self): return spam\n...     return Bar()\n... \n>>> foo().baz()\n\'eggs\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

这在pep 227中有记录:

\n\n
\n

类范围内的名称不可访问。名称在最内层的函数作用域中解析。如果类定义出现在嵌套作用域链中,解析过程将跳过类定义。

\n
\n\n

并在class复合语句文档中:

\n\n
\n

然后,使用新创建的本地命名空间和原始全局命名空间,在新的执行框架中执行 class\xe2\x80\x99s 套件(请参阅命名和绑定部分)。(通常,该套件仅包含函数定义。)当 class\xe2\x80\x99s 套件完成执行时,其执行帧将被丢弃,但其本地命名空间将被保存[4]然后使用基类的继承列表和属性字典保存的本地命名空间创建类对象。

\n
\n\n

强调我的;执行框架是临时范围。

\n