我跟随引发异常的代码:
def a():
b = []
def inner():
b += 3
inner()
print (b)
>>> a()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<console>", line 6, in a
File "<console>", line 5, in inner
UnboundLocalError: local variable 'b' referenced before assignment
但是,如果我重写这样的代码,它会按预期运行:
def a():
b = []
def inner():
b.append(5)
inner()
print(b)
>>> a()
[5]
我想知道为什么会这样,谢谢。
答案 0 :(得分:3)
两者之间的区别在于b += 3
是一个赋值 - 它将一个全新的值(添加空列表的结果和3)分配给b
。相反,b.append()
会改变b
引用的列表而不重新分配它。
inner()
正在访问其父级范围内的变量(我认为这在技术上并不是一个闭包,因为父级的执行尚未完成)。但inner()
只能取消引用该名称,而不能分配给该名称,因为b
不是inner()
的本地名称,并且未声明为global
或nonlocal
。< / p>
因此,您可以取消引用b
并改变它引用的列表,但您无法分配它。当您尝试通过使用b +=
开始分配时,您会说“将b
视为本地”。在正常的b = 3
赋值中,这实际上会成功完成,创建一个局部变量,就像任何其他变量一样。但在这种情况下,由于b
在本地上下文中尚未分配值,因此解除引用b
以执行添加过程失败。
实际上,您不能简单地将整数添加到列表中。 +=
与append
不同,甚至将分配与变异放在一边,所以即使你没有超出范围,它也会因TypeError
而失败。 b += [3]
更接近你的意思,虽然由于变量的范围仍会失败。
答案 1 :(得分:2)
在这里您可以找到确切的解释。 http://eli.thegreenplace.net/2011/05/15/understanding-unboundlocalerror-in-python/
如果您正密切关注StackOverflow上的Python标记,那么您将会这样做 请注意,每周至少会出现一次相同的问题。
&LT; ..&GT;
虽然这个问题在Python的官方常见问题解答(right here)中得到了解答,但是我 决定写这篇文章的目的是给出更深入的解释。
&LT; ..&GT;
那么异常来自哪里?引用常见问题解答:
这是因为当您对作用域中的变量进行赋值时, 该变量变为该范围的本地变量并且影响任何变量 在外部范围内类似命名的变量。