use*_*222 7 python scope class static-binding
在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
Run Code Online (Sandbox Code Playgroud)
类也是代码块,因此我们应该观察到完全相同的行为.但这不是我观察到的.看看这个例子:
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>
Run Code Online (Sandbox Code Playgroud)
由于类定义是一个代码块,因此该块中的任何赋值都应该使变量成为局部变量.所以x应该是本地的C,所以y = x + 10应该导致一个UnboundLocalError.为什么没有这样的错误?
是的 - 似乎该文档相当具有误导性。类定义实际上与其他普通块的工作方式并不完全相同:
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
Run Code Online (Sandbox Code Playgroud)
结果是:10, 120, 30, 0
如果您对某个函数尝试同样的操作,您将UnboundLocalError在第一次访问global_one.
原因是类定义通常可以访问父作用域,但是,所有名称分配不会修改本地作用域,但实际上会被捕获到类的数据属性字典中。文档中对此有一些提示,但肯定不明显。