7

在 python(在 2.7.6 上测试)中,所有变量在编译时都静态绑定到作用域。这个过程在http://www.python.org/dev/peps/pep-0227/http://docs.python.org/2.7/reference/executionmodel.html中有很好的描述

明确指出“如果名称绑定操作发生在代码块内的任何位置,则块内名称的所有使用都被视为对当前块的引用。”

函数是一个代码块,因此下面的代码失败,因为x 是在使用后分配的(因此在编译时它被定义为本地,因为它是在函数中的某处分配的,但在执行时,它是在绑定之前使用的)。

x = 1
def f():
    print x 
    x = 2
    print x

>>> f()

Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    f()
  File "<pyshell#45>", line 2, in f
    print x
UnboundLocalError: local variable 'x' referenced before assignment

一个类也是一个代码块,所以我们应该观察到完全相同的行为。但这不是我观察到的。看这个例子:

x = 1
class C():
    y = x + 10
    x = 2
    def __init__(self):
        print C.y

>>> C.x
2
>>> C.y
11      
>>> C()
11
<__main__.C instance at 0x00000000027CC9C8>

由于类定义是一个代码块,因此该块内的任何赋值都应该使变量成为局部变量。所以x应该是类的本地C,所以y = x + 10应该产生一个UnboundLocalError. 为什么没有这样的错误?

4

1 回答 1

3

是的 - 文档似乎具有误导性。类定义实际上与其他普通块的工作方式不同:

global_one = 0

class A(object):
    x = global_one + 10
    global_one = 100
    y = global_one + 20
    del global_one
    z = global_one + 30

a = A()
print a.x, a.y, a.z, global_one

结果是:10, 120, 30, 0

如果你用一个函数尝试同样的事情,UnboundLocalError你第一次访问global_one.

这样做的原因是类定义通常可以访问父范围,但是,所有名称分配都不会修改本地范围,而是实际上被捕获到类的数据属性字典中。文档中有关于此的提示,但肯定不是很明显。

于 2013-11-24T07:55:54.210 回答