具有嵌套函数作用域的UnboundLocalError

Tho*_*s O 34 python function

我有这样的代码(简化):

def outer():
    ctr = 0

    def inner():
        ctr += 1

    inner()
Run Code Online (Sandbox Code Playgroud)

但是ctr会导致错误:

Traceback (most recent call last):
  File "foo.py", line 9, in <module>
    outer()
  File "foo.py", line 7, in outer
    inner()
  File "foo.py", line 5, in inner
    ctr += 1
UnboundLocalError: local variable 'ctr' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?我认为嵌套的范围可以让我这样做.我试过'全球',但它仍然无效.

Ale*_*lli 42

如果您使用的是Python 3,则可以使用该nonlocal语句启用非本地名称的重新绑定:

def outer():
    ctr = 0

    def inner():
        nonlocal ctr
        ctr += 1

    inner()
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Python 2,那么nonlocal您需要在没有裸名重绑定的情况下执行递增(通过将计数器保留为某个裸名的项或属性,而不是作为裸名本身).例如:

...
ctr = [0]

def inner():
    ctr[0] += 1
...
Run Code Online (Sandbox Code Playgroud)

当然可以ctr[0]ctr其他任何地方使用裸露的地方使用.


Ara*_*Fey 12

说明

每当将值分配给函数内部的变量时,python都会将该变量视为该函数的局部变量。(是否执行赋值都没有关系-只要函数中存在赋值,分配给的变量将被视为该函数的局部变量。)由于该语句ctr += 1包括对ctrpython 的赋值认为ctrinner功能而言是本地的。因此,它甚至从不尝试查看在中ctr定义的变量的值outer。python看到的本质上是这样的:

def inner():
    ctr = ctr + 1
Run Code Online (Sandbox Code Playgroud)

我认为我们都可以同意该代码会导致错误,因为ctr在定义之前就已对其进行了访问。

(另请参阅文档此问题,以获取有关python如何确定变量范围的更多详细信息。)

解决方案(在python 3中)

Python 3引入了nonlocalstatement,它的工作方式与该global语句非常相似,但是让我们可以访问周围函数的变量(而不是全局变量)。只需nonlocal ctrinner函数顶部添加,问题就会消失:

def outer():
    ctr = 0

    def inner():
        nonlocal ctr
        ctr += 1

    inner()
Run Code Online (Sandbox Code Playgroud)

解决方法(在python 2中)

由于该nonlocal语句在python 2中不存在,因此我们必须要有技巧。有两种简单的解决方法:

  • 删除所有分配给 ctr

    由于python只考虑ctr了局部变量,因为对该变量进行了赋值,所以如果我们删除对name的所有赋值,问题就会消失ctr。但是,如何在不赋值​​的情况下更改变量的值呢?简单:我们将变量包装在一个可变对象中,例如列表。然后,我们无需修改名称即可修改该列表ctr

    def outer():
        ctr = [0]
    
        def inner():
            ctr[0] += 1
    
        inner()
    
    Run Code Online (Sandbox Code Playgroud)
  • ctr作为参数传递给inner

    def outer():
        ctr = 0
    
        def inner(ctr):
            ctr += 1
            return ctr
    
        ctr = inner(ctr)
    
    Run Code Online (Sandbox Code Playgroud)

  • 我总是很欣赏解释特定行为的答案,而不是仅仅放置一段代码。+1 (4认同)

dan*_*ben 6

来自http://www.devshed.com/c/a/Python/Nested-Functions-in-Python/1/

嵌套函数体中的代码可以访问(但不重新绑定)外部函数的局部变量,也称为嵌套函数的自由变量.

所以,你需要传递ctrinner明确.


归档时间:

查看次数:

6811 次

最近记录:

5 年,11 月 前