但是这个答案说问题在于分配给x。如果是这样,那么打印它应该可以正常工作,不是吗?
你必须了解事情发生的顺序。在你的 python 代码甚至被编译和执行之前,一个叫做解析器的东西会读取 python 代码并检查语法。解析器所做的另一件事是将变量标记为本地变量。当解析器在本地范围内的代码中看到赋值时,赋值左侧的变量被标记为本地。那时,甚至还没有编译任何东西——更不用说执行了,因此没有发生赋值;该变量仅被标记为局部变量。
解析器完成后,代码被编译并执行。当执行到达打印语句时:
def main():
x = 10 #<---x in enclosing scope
def f():
print x #<-----
x = x + 1 #<-- x marked as local variable inside the function f()
打印语句看起来应该继续并在封闭范围内打印 x(LEGB 查找过程中的“E”)。然而,因为解析器之前将 x 标记为 f() 中的局部变量,python 不会继续越过局部范围(LEGB 查找过程中的“L”)来查找 x。因为在执行 'print x' 时 x 尚未在本地范围内分配,所以 python 吐出一个错误。
请注意,即使发生赋值的代码永远不会执行,解析器仍然会将赋值左侧的变量标记为局部变量。解析器不知道事情将如何执行,因此它盲目地在整个文件中搜索语法错误和局部变量——即使是在永远无法执行的代码中。以下是一些例子:
def dostuff ():
x = 10
def f():
print x
if False: #The body of the if will never execute...
a b c #...yet the parser finds a syntax error here
return f
f = dostuff()
f()
--output:--
File "1.py", line 8
a b c
^
SyntaxError: invalid syntax
解析器在标记局部变量时做同样的事情:
def dostuff ():
x = 10
def f():
print x
if False: #The body of the if will never execute...
x = 0 #..yet the parser marks x as a local variable
return f
f = dostuff()
f()
现在看看当你执行最后一个程序时会发生什么:
Traceback (most recent call last):
File "1.py", line 11, in <module>
f()
File "1.py", line 4, in f
print x
UnboundLocalError: local variable 'x' referenced before assignment
当语句 'print x' 执行时,因为解析器将 x 标记为局部变量,所以对 x 的查找会在局部范围内停止。
这个“特性”并不是python独有的——它也发生在其他语言中。
至于数组示例,当您编写时:
x[0] = x[0] + 1
这告诉 python 去查找一个名为 x 的数组并将某些东西分配给它的第一个元素。因为在局部范围内没有对任何名为 x 的东西进行赋值,所以解析器不会将 x 标记为局部变量。