具有嵌套函数范围的UnboundLocalError[重复]
- 2025-02-05 13:24:00
- admin 原创
- 77
问题描述:
我有这样的代码(简化):
def outer():
ctr = 0
def inner():
ctr += 1
inner()
但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
我该如何解决这个问题?我以为嵌套范围可以让我做到这一点。我尝试使用“全局”,但仍然不起作用。
解决方案 1:
如果您使用的是 Python 3,则可以使用该nonlocal
语句启用非本地名称的重新绑定:
def outer():
ctr = 0
def inner():
nonlocal ctr
ctr += 1
inner()
如果您使用的是没有 的 Python 2,nonlocal
则需要在不重新绑定 barename 的情况下执行递增(通过将计数器保留为某些 barename 的项目或属性,而不是barename 本身)。例如:
...
ctr = [0]
def inner():
ctr[0] += 1
...
当然,无论ctr[0]
您现在在其他地方使用裸机,都可以使用ctr
。
解决方案 2:
解释
每当将值赋给函数内的变量时,python 都会将该变量视为该函数的局部变量。(赋值是否执行并不重要 - 只要函数中存在ctr += 1
赋值,被赋值的变量就会被视为该函数的局部变量。)由于语句包含对 的赋值ctr
,因此 python 认为ctr
是inner
函数的局部变量。因此,它甚至不会尝试查看ctr
中定义的变量的值outer
。python 看到的基本上是这样的:
def inner():
ctr = ctr + 1
我认为我们都同意这段代码会导致错误,因为ctr
它在定义之前就被访问了。
(有关python 如何决定变量范围的更多详细信息,另请参阅文档或这个问题。)
解决方案(使用 Python 3)
Python 3 引入了nonlocal
语句,其工作原理与语句非常相似global
,但允许我们访问周围函数的变量(而不是全局变量)。只需nonlocal ctr
在函数顶部添加inner
,问题就会消失:
def outer():
ctr = 0
def inner():
nonlocal ctr
ctr += 1
inner()
解决方法(在 Python 2 中)
由于该nonlocal
语句在 Python 2 中不存在,因此我们必须采取一些巧妙的方法。有两种简单的解决方法:
删除所有分配到
ctr
由于 python 仅考虑ctr
局部变量,因为该变量有一个赋值,如果我们删除对 name 的所有赋值,问题就会消失ctr
。但是我们如何才能在不赋值的情况下改变变量的值呢?很简单:我们将变量包装在一个可变对象中,比如一个列表。然后我们可以修改该列表,而无需为 name 赋值ctr
:
def outer():
ctr = [0]
def inner():
ctr[0] += 1
inner()
ctr
作为参数传递给inner
def outer():
ctr = 0
def inner(ctr):
ctr += 1
return ctr
ctr = inner(ctr)
解决方案 3:
ctr
那么在外部(即在全局范围内)或任何其他类/函数中声明怎么样outer
?这将使变量可访问和可写。