以下代码提出了UnboundLocalError
:
def foo(): i = 0 def incr(): i += 1 incr() print(i) foo()
有没有办法实现这个目标?
使用nonlocal
声明
def foo(): i = 0 def incr(): nonlocal i i += 1 incr() print(i) foo()
有关python 3.x中添加的新语句的更多信息,请访问https://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement
你可以i
像这样使用一个参数:
def foo(): i = 0 def incr(i): return i + 1 i = incr(i) print(i) foo()
见9.2.Python范围和命名空间:
如果没有
global
语句生效 - 名称的赋值总是进入最内层范围.
也:
该
global
陈述可用于表明特定变量存在于全球范围内,并应在那里反弹; 该nonlocal
陈述表明特定变量存在于封闭范围内,应该在那里反弹.
你有很多解决方案:
i
作为参数传递✓(我会选择这个)
使用nonlocal
关键字
请注意,在Python2.x中,您可以访问非局部变量,但无法更改它们.
人们已经回答了你的问题,但似乎没有人解决为什么会发生这种情况.
以下代码提出了一个问题
UnboundLocalError
那么,为什么呢?让我们从FAQ中引用:
当您对作用域中的变量进行赋值时,该变量将成为该作用域的局部变量,并在外部作用域中隐藏任何类似命名的变量.
在嵌套函数中,您正在与+=
运算符执行赋值.这意味着i += 1
将近似执行i = i + 1
(从绑定的角度来看).因此i
,i + 1
将在本地范围内搜索表达式(因为它在赋值语句中使用)incr
,因为它将无法找到它的函数,从而产生一个UnboundLocalError: reference before assignment
.
有很多方法可以解决这个问题,python 3在你可以采用的方法上比python 2更优雅.
Python 3nonlocal
:
这些nonlocal
语句告诉Python在foo()
名称引用的封闭范围内查找名称(在本例中,在函数范围内):
def foo(): i = 0 def incr(): nonlocal i i +=1 incr() print(i)
函数属性Python 2.x
和3.x
:
请记住,函数是第一类对象,因此它们可以存储状态.使用函数属性来访问和改变函数状态,这种方法的好处是它适用于所有 pythons并且不需要global, nonlocal
语句.
def foo(): foo.i = 0 def incr(): foo.i +=1 incr() print(foo.i)
该global
声明(Python的2.x
,3.x
):
真是最丑陋的一群,但完成了工作:
i = 0 def foo(): def incr(): global i i += 1 incr() print(i) foo()
将参数传递给函数的选项获得相同的结果,但它与在某种意义上改变封闭范围无关nonlocal
,global
而且更像是所呈现的函数属性.它正在函数中创建一个新的局部变量inc
,然后将名称重新绑定到i
,i = incr(i)
但它确实完成了工作.