为什么会出现这个UnboundLocalError(闭包)?

223 投票
8 回答
303037 浏览
提问于 2025-04-17 12:58

我这里做错了什么呢?

counter = 0

def increment():
  counter += 1

increment()

上面的代码会报一个叫做 UnboundLocalError 的错误。

8 个回答

30

针对你标题中的问题,* 是的,Python中确实有闭包,不过它们只在函数内部有效。而且在Python 2.x中,闭包是只读的;你不能把名字重新绑定到一个不同的对象上(不过如果这个对象是可变的,你可以修改它的内容)。在Python 3.x中,你可以使用nonlocal这个关键词来修改闭包变量。

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

increment = incrementer()

increment()   # 1
increment()   # 2

* 这个问题最开始是问Python中的闭包。

95

你需要使用 global 语句,这样你才能修改全局变量 counter,而不是局部变量:

counter = 0

def increment():
  global counter
  counter += 1

increment()

如果定义 counter 的作用域不是全局作用域,在 Python 3.x 中你可以使用 nonlocal 语句。而在 Python 2.x 中,如果遇到同样的情况,你就无法重新赋值给非局部的名字 counter,所以你需要让 counter 可变并进行修改:

counter = [0]

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

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

Python没有变量声明,所以它需要自己判断变量的作用域。它是通过一个简单的规则来做到这一点的:如果在一个函数内部给一个变量赋值,那么这个变量就被认为是局部变量。[1] 也就是说,下面这一行

counter += 1

会让counter被视为increment()函数中的局部变量。不过,如果你在执行这行代码时,试图在给counter赋值之前读取它的值,就会出现一个错误,叫做UnboundLocalError[2]

如果counter是一个全局变量,使用global关键字会有所帮助。如果increment()是一个局部函数,而counter是一个局部变量,你可以在Python 3.x中使用nonlocal

撰写回答