好的,在阅读了 Doug 和 Jim 的回答后,我想我知道这是如何工作的。首先,所有示例都在 REPL 中工作(Ipython,默认)
文件:如果你把它写在一个文件中:
if True:
print("Hi")
else:
I am an error. What can you do about it?
并运行该文件,它会抛出一个 SyntaxError。这证明了每当我们从文件中执行 python 代码时,它都会生成一个字节码,并且由于 else 中的语句不是有效的 python 表达式,我们会得到一个 SyntaxError。
REPL:使用 REPL,事情变得有点依赖。在 python 解释器中,如果你输入
>>>def foo():
if True:
print("Hey")
else:
I am an error. What can you do about it?
>>>foo()
Hey
成功执行意味着没有字节码,对吗?坚持,稍等。
如果你这样写:
>>>x = 10
>>>def foo():
print(x)
x += 1
>>>foo()
和繁荣!一切都崩溃了,您在 print(x) 语句中得到 UnboundLocalError 。这意味着字节码在那里。
那么这里到底发生了什么?
如果 python 发现一个变量的单个出现,它会尝试通过首先读取所有变量来优化其工作。因此,在第二个示例中,当代码遇到 print(x) 时,它会尝试查找 x 上的所有操作。很快它就找到了语句 x+=1。由于在局部范围内没有提及 x 并且如果没有明确提及,python 永远不会在全局范围内查找变量,我们有
UnboundLocalError: local variable 'x' is referenced before assignment
确凿的证明
如果我们这样写:
>>>x = 10
>>>def foo():
if True:
print(x)
else:
x+=1
>>>foo()
UnboundLocalError: local variable 'x' referenced before assignment
而已!
x+=1 永远不会被执行,但是由于 print 语句打印 x 并且另一个引用 (x+=1) 是问题,因此在打印值之前遇到了错误。第一种情况在 REPL 中没有 SyntaxError 时运行良好,因为它从不费心查看 else 语句,因为它无关紧要。