使用 UnboundLocalError 的本地和全局引用

Local and global references with UnboundLocalError

我不太明白为什么代码

def f():
    print(s)

s = "foo"
f()

运行得很好但是

def f():
    print(s)
    s = "bar"

s = "foo"
f()

给我 UnboundLocalError。我知道我可以通过将 s 声明为函数内部的全局变量或简单地将 s 参数传递给函数来解决此问题。

我还是不明白python怎么知道在该行执行之前函数内部是否引用了s?当函数被读入全局框架时,python 是否生成某种所有局部变量引用的列表?

是的,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 试图在全局范围内找到它,但它不存在。

其他答案都集中在这方面的实际方面,但没有真正回答你问的问题。

是的,Python 编译器会在编译代码块(例如在 def 中)时跟踪分配了哪些变量。如果在块中分配了一个名称,编译器将其标记为 local.Take 查看 function.__code__.co_varnames 以查看编译器已识别哪些变量。

nonlocalglobal 语句可以覆盖它。