类范围中的闭包

时间:2012-11-14 15:30:47

标签: python class scope

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

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


>>> class x():
...     a = 123
...     print (locals())
... 
{'a': 123, '__module__': '__main__'}

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

>>> def x():
...     a = 123
...     t = lambda: a
...     return t
... 
>>> x()()
123

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

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

有人可以解释这种差异吗?

1 个答案:

答案 0 :(得分:4)

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

就类中定义的函数而言,下一个范围“up”是class定义本身的范围。

以下工作正常:

>>> def foo():
...     spam = 'eggs'
...     class Bar(object):
...         def baz(self): return spam
...     return Bar()
... 
>>> foo().baz()
'eggs'

pep 227中记录了这一点:

  

无法访问类范围中的名称。名称已解决       最里面的封闭功能范围。如果是一个类定义       在嵌套范围链中发生,解析过程会跳过       类定义。

class compound statement documentation

  

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

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