“赋值前引用的局部变量” - 只有函数?

时间:2012-01-31 23:33:42

标签: python scope

请使用以下代码:

import something

def Foo():
    something = something.SomeClass()
    return something

......这显然不是有效的代码:

UnboundLocalError: local variable 'something' referenced before assignment

...在评估something的RHS之前,创建了局部变量=但未分配。 (例如,参见this related answer's comment。)这对我来说有点奇怪,但当然,我会继续使用它。现在,为什么以下有效代码?

class Foo(object):
    something = something.SomeClass()

我的理解是class定义的内部基本上是一个范围:

  

然后使用新创建的本地命名空间和原始全局命名空间,在新的执行框架中执行类的套件(请参阅命名和绑定一节)。

那么,那么,为什么那些代码的行为与函数的行为不同呢?

2 个答案:

答案 0 :(得分:6)

来自python class documentation

  

类定义在本地范围内放置另一个命名空间。

     

Python的一个特殊之处在于 - 如果没有全局语句生效 - 对名称的赋值总是进入最内层范围。分配不复制数据 - 它们只是将名称绑定到对象。删除也是如此:语句del x删除了x与本地范围引用的命名空间的绑定。实际上,引入新名称的所有操作都使用本地范围:特别是,import语句和函数定义绑定本地范围中的模块或函数名称。 (全局语句可用于指示特定变量存在于全局范围内。)

因此,在函数(或范围)中,赋值创建一个在绑定之前访问的本地未绑定变量,而在类定义中,它在赋值时在该类的“命名空间”字典中创建一个条目,允许将something解析为外部命名空间(模块命名空间)。

答案 1 :(得分:5)

请考虑以下示例,这可能有助于澄清这一点:

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不明确(就像在函数中使用相同的代码一样)

总之,由于类定义创建了新的命名空间以及新的范围,因此您可以直接访问封闭范围中的名称并在本地范围内指定相同的名称。