请使用以下代码:
import something
def Foo():
something = something.SomeClass()
return something
......这显然不是有效的代码:
UnboundLocalError: local variable 'something' referenced before assignment
......作为局部变量 something
在RHS之前创建,但未分配 =
被评估。 (例如,参见 这个相关答案的评论对我来说这看起来有点奇怪,但当然,我会顺其自然。现在,为什么以下有效代码?
class Foo(object):
something = something.SomeClass()
我的理解是内心的 class
定义本质上是一个范围:
然后,使用新创建的本地命名空间和原始全局命名空间,在新的执行框架中执行类的套件(请参阅命名和绑定一节)。
那么,为什么这些代码的行为与函数的行为不同?
来自 python类文档:
类定义在本地范围中放置另一个命名空间。
Python的一个特殊之处在于 - 如果没有全局语句生效 - 对名称的赋值总是进入最内层范围。分配不复制数据 - 它们只是将名称绑定到对象。删除也是如此:语句del x删除了x与本地范围引用的命名空间的绑定。实际上,引入新名称的所有操作都使用本地范围:特别是,import语句和函数定义绑定本地范围中的模块或函数名称。 (全局语句可用于指示特定变量存在于全局范围内。)
因此,在函数(或范围)中,赋值创建一个在绑定之前访问的本地未绑定变量,而在类定义中,它在赋值时在该类的“命名空间”字典中创建一个条目,允许解析 something
到外部命名空间(模块命名空间)。
请考虑以下示例,这可能有助于澄清这一点:
import datetime
class Foo(object):
datetime = datetime.datetime
>>> datetime
<module 'datetime' from '/usr/lib/python2.6/lib-dynload/datetime.so'>
>>> Foo.datetime
<type 'datetime.datetime'>
注意这一行 datetime = datetime.datetime
实际上是分配给名称 Foo.datetime
,这与全球性并不含糊 datetime
(就像在函数中使用相同的代码一样)。
总之,由于类定义创建了新的命名空间以及新的范围,因此您可以直接访问封闭范围中的名称并在本地范围中指定相同的名称。