我不太明白为什么代码
def f():
print(s)
s = "foo"
f()
运行得非常好,但
def f():
print(s)
s = "bar"
s = "foo"
f()
给我UnboundLocalError。我知道我可以通过将 s 声明为函数内部的全局变量或者只是将 s 一个参数传递给函数来解决这个问题。
我仍然不明白python如何知道在执行该行之前是否在函数内部引用了s?当函数被读入全局框架时,python是否会创建所有局部变量引用的某种列表?
答案 0 :(得分:1)
是的,Python将预先恢复在本地范围内声明的所有变量。这些将掩盖全球变量。
所以在你的代码中:
def f():
print(s)
s = "foo"
f()
Python在本地范围内未找到s
,因此它尝试从全局范围中恢复它并找到"foo"
。
现在在另一种情况下会发生以下情况:
def f():
print(s)
s = "bar
s = "foo"
f()
Python知道s
是一个局部变量,因为它在运行时之前进行了预测,但是在运行时它还没有被分配,所以它被引发和异常。
请注意,Python甚至可以让您引用尚未在任何地方声明的变量。如果你这样做:
def foo():
return x
f()
你会得到一个NameError
,因为Python在没有找到x
作为局部变量时会记得在运行时它应该寻找一个名为x
的全局变量然后如果它不存在则失败。
所以UnboundLocalError
意味着变量最终可能在范围内声明但尚未声明。另一方面,NameError
意味着变量永远不会在本地范围内声明,因此Python试图在全局范围内找到它,但它不存在。
答案 1 :(得分:1)
其他答案都集中在这方面的实际方面,但实际上并没有回答你提出的问题。
是的,Python编译器跟踪在编译代码块时分配的变量(例如在def
中)。如果在块中指定了名称,则编译器将其标记为本地。请查看function.__code__.co_varnames
以查看编译器已识别的变量。
nonlocal
和global
语句可以覆盖此内容。