不明白为什么会发生UnboundLocalError

Ran*_*lue 153 python scope global-variables

我在这做错了什么?

counter = 0

def increment():
  counter += 1

increment()
Run Code Online (Sandbox Code Playgroud)

上面的代码抛出了一个UnboundLocalError.

Sve*_*ach 150

Python没有变量声明,因此必须弄清楚变量本身的范围.它通过一个简单的规则来实现:如果对函数内部的变量赋值,则该变量被视为本地变量.[1] 因此,这条线

counter += 1
Run Code Online (Sandbox Code Playgroud)

隐含地使counter本地化increment().但是,尝试执行此行将尝试counter在分配之前读取局部变量的值,从而产生一个UnboundLocalError.[2]

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

  • python 3 docs有一个[faq页面上关于为什么 - 我正在获取一个unboundlocalerror-when-the-variable-has-a-value](https://docs.python.org/3/faq/programming. html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value)来自[unboundlocalerror-local-variable-l-referenced-before-assignment-python](http:// stackoverflow .COM /问题/ 21456739/unboundlocalerror局部变量-1-引用前方的分配的Python) (7认同)

And*_*ark 79

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

counter = 0

def increment():
  global counter
  counter += 1

increment()
Run Code Online (Sandbox Code Playgroud)

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

counter = [0]

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

increment()
print counter[0]  # prints '1'
Run Code Online (Sandbox Code Playgroud)


kin*_*all 19

要回答主题中的问题,*是,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
Run Code Online (Sandbox Code Playgroud)

*原始问题的标题询问了Python中的闭包.


Rik*_*ggi 7

您的代码抛出的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)
Run Code Online (Sandbox Code Playgroud)


Chr*_*lor 5

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

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

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

>>> x = 1

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

>>> f()
1
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

179124 次

最近记录:

6 年,1 月 前