“分配前引用的局部变量” - 仅有函数?

问题描述:

看看下面的代码:“分配前引用的局部变量” - 仅有函数?

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定义的内部基本上是一个范围:

类的套件,然后在新的执行框架(参见命名和结合)执行时,使用新创建本地名称空间和原始全局名称空间。

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

+0

'something'似乎有多个含义? – Johnsyweb 2012-01-31 23:39:09

+0

@Johnsyweb:是的,有点。但是在这两种情况下,它都具有相同的多种含义。 (或者,至少,我读过的所有文档似乎都这样说)。 – Thanatos 2012-02-01 02:26:40

请看下面的例子可能有助于澄清这一点:

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暧昧(好像是,如果函数中有相同的代码)。

总之,由于类定义会创建一个新的名称空间以及一个新的作用域,因此您可以直接访问封闭作用域中的名称并在本地作用域中分配相同的名称。

+0

“请注意,datetime = datetime.datetime这一行实际上是分配给名称'Foo。datetime',这与全局的'datetime'没有什么不明确性 - “No:它指定给名字'datetime':如果你添加两个'print datetime'语句,一个在'datetime ='之前,一个之后,在该语句中是'datetime' *不*含糊不清,以某种方式与函数中的同一个语句不同¶ – Thanatos 2012-02-01 02:10:09

+0

@Thanatos - 是的,我可以看到这怎么不清楚,我想说的是命名空间由类创建允许一个明确的方式来访问其他范围的全局和类属性,但你是正确的仍然是在本地范围内的含糊不清。 – 2012-02-01 17:20:32

+0

但问题的关键是这是如何不同而不是函数中发生的事情?你声明,“因为类定义创建了一个新的名称空间和一个新的作用域” - 不要函数同时创建一个新的名称空间和一个新的作用域 - “你可以直接访问一个名字一个封闭的范围“ - 我可以做这在一个函数中 - “并在本地作用域中分配相同的名称” - 我只能在类定义中执行此操作...为什么? – Thanatos 2012-02-01 19:55:46

python class documentation

类定义发生在局部范围内的另一个命名空间。

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

左右的时间内一个函数(或范围)的分配产生势必之前被访问的本地绑定变量,而在类定义中,它在分配时在该类的“名称空间”字典中创建一个条目,允许将外部名称空间(模块名称空间)的something分辨率。