Kan*_* Li 6 python scope nested-function
有人可以解释为什么以下程序失败:
def g(f):
for _ in range(10):
f()
def main():
x = 10
def f():
print x
x = x + 1
g(f)
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
随着消息:
Traceback (most recent call last):
File "a.py", line 13, in <module>
main()
File "a.py", line 10, in main
g(f)
File "a.py", line 3, in g
f()
File "a.py", line 8, in f
print x
UnboundLocalError: local variable 'x' referenced before assignment
Run Code Online (Sandbox Code Playgroud)
但是,如果我只是将变量更改为x数组,它的工作原理如下:
def g(f):
for _ in range(10):
f()
def main():
x = [10]
def f():
print x[0]
x[0] = x[0] + 1
g(f)
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
与输出
10
11
12
13
14
15
16
17
18
19
Run Code Online (Sandbox Code Playgroud)
我感到困惑的原因是,如果从f()它无法访问x,为什么它变得可访问,如果x是一个数组?
谢谢.
但这个答案说问题出在分配给 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()
Run Code Online (Sandbox Code Playgroud)
print 语句看起来应该继续并打印 x 中的 x封闭范围内的 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
Run Code Online (Sandbox Code Playgroud)
解析器在标记局部变量时做同样的事情:
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()
Run Code Online (Sandbox Code Playgroud)
现在看看执行最后一个程序时会发生什么:
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
Run Code Online (Sandbox Code Playgroud)
当语句“print x”执行时,由于解析器将 x 标记为局部变量,因此对 x 的查找将停止在局部范围内。
这个“特性”并不是 Python 所独有的——它也存在于其他语言中。
至于数组示例,当您编写:
x[0] = x[0] + 1
Run Code Online (Sandbox Code Playgroud)
它告诉 python 查找名为 x 的数组并将某些内容分配给它的第一个元素。由于在本地作用域中没有对任何名为 x 的内容进行赋值,因此解析器不会将 x 标记为本地变量。
| 归档时间: |
|
| 查看次数: |
295 次 |
| 最近记录: |