Python 不理解为什么会发生UnboundLocalError(闭包)

Python 不理解为什么会发生UnboundLocalError(闭包),python,scope,closures,global-variables,Python,Scope,Closures,Global Variables,我做错了什么 counter = 0 def increment(): counter += 1 increment() 上面的代码抛出一个UnboundLocalError。要修改函数中的全局变量,必须使用global关键字 当你尝试在没有线的情况下这样做时 global counter 在增量的定义中,创建了一个名为counter的局部变量,以避免弄乱整个程序可能依赖的计数器变量 请注意,修改变量时只需使用全局变量;您可以从增量中读取计数器,而不需要全局语句。您需要使用,以便修改

我做错了什么

counter = 0

def increment():
  counter += 1

increment()

上面的代码抛出一个UnboundLocalError。

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

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

global counter
在增量的定义中,创建了一个名为counter的局部变量,以避免弄乱整个程序可能依赖的计数器变量

请注意,修改变量时只需使用全局变量;您可以从增量中读取计数器,而不需要全局语句。

您需要使用,以便修改全局变量计数器,而不是局部变量:

counter = 0

def increment():
  global counter
  counter += 1

increment()
如果定义计数器的封闭范围不是全局范围,那么在Python3.x上可以使用。在Python 2.x上的相同情况下,您将无法重新分配给非本地名称计数器,因此需要使计数器可变并修改它:

counter = [0]

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

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

counter = 0

def increment():
  global counter
  counter += 1

increment()

Python不是纯粹的词汇范围

见此:


这是:

Python没有变量声明,因此它必须找出变量本身的定义。它是通过一个简单的规则来实现的:如果函数中有一个变量赋值,那么该变量被认为是局部变量。因此,这条线

counter += 1
隐式地使计数器局部递增。但是,如果尝试执行这一行,将尝试在赋值之前读取局部变量计数器的值,从而导致错误


如果计数器是一个全局变量,则关键字将有帮助。如果increment是一个局部函数,并且计数器是一个局部变量,那么您可以在Python 3.x中使用。

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

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

在您的例子中,您试图将计数器视为局部变量,而不是绑定值。请注意,此代码绑定在封闭环境中指定的x值,工作正常:

>>> x = 1

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

>>> f()
1

为了回答主题行中的问题,*是的,Python中有闭包,只是它们只应用于函数内部,在Python2.x中也是只读的;不能将名称重新绑定到其他对象,但如果该对象是可变的,则可以修改其内容。在Python3.x中,可以使用关键字修改闭包变量

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

increment = incrementer()

increment()   # 1
increment()   # 2

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

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

但在我看来,你似乎在试图建立一个类似于

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

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

python 3文档中有一个让我吃惊的注释,我在文件顶部声明了一个变量,我可以在函数中读取该变量,但要写入我在文件顶部声明的变量,我必须使用全局变量。更深入的解释:。不仅赋值可以绑定名称,导入也可以绑定名称,因此您还可以从使用无界导入名称的语句中获取UnboundLocalError。示例:def foo:bar=deepcopy{'a':1};从复制导入深度复制;返回栏,然后从复制导入deepcopy;福。如果从副本导入deepcopy的本地导入被删除,则调用将成功。此问题及其当前标记为重复的问题正在中讨论。这里的许多答案都说使用全局,尽管这样做有效,当存在其他选项时,通常不建议使用可修改的globals。@ZeroPiraeus 2012年提出的问题不能与2016年提出的问题重复。。。相反,较新的版本是重复的。@dsh.@juanpa.arrivillaga尽管一般问题是结束并更新非本地的绑定。完全局部变量也可能发生UnboundLocalError,但它们是一个不同的问题,具有不同的解决方案。虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,则仅链接的答案可能无效-