为什么会出现此UnboundLocalError(闭包)



我做错了什么?

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

上面的代码抛出一个UnboundLocalError

Python没有变量声明,所以它必须自己计算变量的范围。它通过一个简单的规则来做到这一点:如果函数中有一个变量的赋值,则该变量被视为局部变量<因此,线>

counter += 1

隐式地使CCD_ 2对于CCD_。但是,尝试执行此行将尝试在分配局部变量counter之前读取其值,从而生成UnboundLocalError[2]

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

您需要使用全局语句来修改全局变量计数器,而不是本地变量:

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

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

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

要回答主题行中的问题,*是的,Python中有闭包,只是它们只应用于函数内部,而且(在Python 2.x中)它们是只读的;您不能将名称重新绑定到不同的对象(尽管如果对象是可变的,您可以修改其内容)。在Python3.x中,可以使用nonlocal关键字来修改闭包变量。

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

*这个问题最初是关于Python中闭包的。

您的代码抛出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)

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

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

在您的案例中,您试图将counter视为局部变量,而不是绑定值。请注意,这段代码绑定了在封闭环境中分配的x的值,运行良好:

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

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

当你尝试在没有线路的情况下这样做时

global counter

在增量的定义中,创建了一个名为counter的局部变量,这样可以防止您混淆整个程序可能依赖的计数器变量。

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

试试这个:

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

Python不是纯粹的词法范围。

请参阅在函数中使用全局变量

以及关于Python变量范围的注释

相关内容

  • 没有找到相关文章

最新更新