我哪里做错了?

counter = 0

def increment():
  counter += 1

increment()

上面的代码抛出一个UnboundLocalError。


当前回答

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

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

在您的情况下,您试图将counter视为局部变量而不是绑定值。注意,这段代码绑定了在封闭环境中赋值的x,工作正常:

>>> x = 1

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

>>> f()
1

其他回答

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

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

在您的情况下,您试图将counter视为局部变量而不是绑定值。注意,这段代码绑定了在封闭环境中赋值的x,工作正常:

>>> x = 1

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

>>> f()
1

试试这个:

counter = 0

def increment():
  global counter
  counter += 1

increment()

您的代码抛出UnboundLocalError的原因已经在其他答案中得到了很好的解释。

但在我看来,您正在尝试构建类似itertools.count()的东西。

所以试试吧,看看它是否适合你的情况:

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

你需要使用global语句来修改全局变量计数器,而不是局部变量:

counter = 0

def increment():
  global counter
  counter += 1

increment()

如果定义计数器的封闭作用域不是全局作用域,则在Python 3上。你可以使用非局部语句。在Python 2中也是如此。X你将没有办法重新分配给非本地名称计数器,所以你需要使计数器可变并修改它:

counter = [0]

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

increment()
print counter[0]  # prints '1'

要在函数中修改全局变量,必须使用global关键字。

当你试着不画线的时候

global counter

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

注意,只有在修改变量时才需要使用global;您可以从增量中读取counter,而不需要全局语句。