5

据我了解,函数和类作用域的行为几乎相同:

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

谁能解释这种差异?

4

1 回答 1

4

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

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

以下工作正常:

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

这记录在pep 227中:

类范围内的名称不可访问。名称在最里面的封闭函数范围内解析。如果类定义出现在嵌套范围链中,则解析过程会跳过类定义。

并在class复合语句文档中:

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

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

于 2012-11-14T15:37:30.270 回答