Python中的UnboundLocalError

我在这里做错了什么?

counter = 0 def increment(): counter += 1 increment() 

上面的代码抛出一个UnboundLocalError

Python没有variables声明,所以它必须找出variables本身的范围 。 这是通过一个简单的规则来实现的:如果函数内部有一个variables赋值,该variables被认为是本地的。 [1]因此,线

 counter += 1 

隐式地使counter本地increment() 。 尽pipe如此,尝试执行这一行将尝试在分配之前读取局部variablescounter的值,导致UnboundLocalError[2]

如果counter是一个全局variables,那么global关键字将会有所帮助。 如果increment()是一个本地函数并counter一个局部variables,那么可以在Python 3.x中使用nonlocal

您需要使用全局语句,以便您修改全局variables计数器,而不是本地variables:

 counter = 0 def increment(): global counter counter += 1 increment() 

如果counter在其中定义的封闭范围不是全局范围,那么在Python 3.x上,可以使用非本地语句 。 在Python 2.x的相同情况下,您将无法重新分配非本地名称counter ,因此您需要使counter变为可变并对其进行修改:

 counter = [0] def increment(): counter[0] += 1 increment() print counter[0] # prints '1' 

要回答你的主题中的问题,*是的,在Python中有闭包,除了它们只应用在函数内部,并且(在Python 2.x中)它们是只读的; 你不能将名字重新绑定到不同的对象(尽pipe如果对象是可变的,你可以修改它的内容)。 在Python 3.x中,可以使用nonlocal关键字来修改一个闭包variables。

 def incrementer(): counter = 0 def increment(): nonlocal counter counter += 1 return counter return increment increment = incrementer() increment() # 1 increment() # 2 

*原始问题的标题问到关于Python中的闭包。

其他答案已经很好地解释了为什么你的代码抛出一个UnboundLocalError的原因。

但在我看来,你正在尝试构build像itertools.count()一样工作的东西。

那么你为什么不尝试一下,看看它是否适合你的情况:

 >>> from itertools import count >>> counter = count(0) >>> counter count(0) >>> next(counter) 0 >>> counter count(1) >>> next(counter) 1 >>> counter count(2) 

要修改函数内的全局variables,您必须使用全局关键字。

当你尝试这样做没有线

 global counter 

在增量定义的内部,创build了一个名为counter的局部variables,以防止整个程序可能依赖的计数器variables。

请注意,只有在修改variables时才需要使用全局variables; 你可以从增量内读取计数器,而不需要全局声明。

Python默认使用词法作用域,这意味着虽然封闭作用域可以访问其封闭作用域中的值,但不能修改它们(除非它们是用global关键字声明为global )。

闭包将封闭环境中的值绑定到本地环境中的名称。 然后本地环境可以使用绑定值,甚至可以将该名称重新分配给别的东西,但是它不能修改封闭环境中的绑定。

在你的情况下,你正试图把counter作为局部variables而不是绑定值。 请注意,这个绑定在封闭环境中分配的x值的代码工作正常:

 >>> x = 1 >>> def f(): >>> return x >>> f() 1 

尝试这个

 counter = 0 def increment(): global counter counter += 1 increment() 

Python不是纯粹的词汇范围。

看到这个: 在创build它们的函数中使用全局variables

和这个: http : //www.saltycrane.com/blog/2008/01/python-variable-scope-notes/