外部函数中的嵌套函数更改变量不起作用
Posted
技术标签:
【中文标题】外部函数中的嵌套函数更改变量不起作用【英文标题】:nested function change variable in an outside function not working 【发布时间】:2017-05-07 19:46:20 【问题描述】:def some_func(a):
def access_a():
print(a)
access_a()
输出a
的值。但是,如果我想像这样在嵌套函数中更改a
:
def some_func(a):
def change_a():
a += 1
print(a)
change_a()
它引发UnboundLocalError
异常。
我知道a
是一个非局部变量,但是为什么我可以不声明nonlocal a
就访问它呢?
【问题讨论】:
你在函数中试过global a
吗?
这和global
是一样的:你可以访问一个全局变量,但是在没有global var
的情况下尝试修改它会失败。
不管有什么方法可以解决这个问题,像这样伸出手并导致任意副作用都不是好的编程习惯。
...所以你一开始就不应该这样做。
【参考方案1】:
Python 范围规则 101:
除非明确声明 global
(Python 2.x 和 3.x)或 nonlocal
(仅限 Python 3.x),否则绑定在函数体中的名称被视为 local
。这适用于函数体中发生赋值的任何地方。在绑定之前尝试读取局部变量当然是错误的。
请注意,a += 1
主要是 a = a + 1
的快捷方式,因此在您的示例中,a
是本地的(绑定在函数的主体中,没有明确声明为全局或非本地),但您尝试阅读它(rhs a = a+1
) 在绑定之前。
在 Python 3 中,您可以使用 nonlocal
语句解决此问题:
>>> def outer(a):
... def change():
... nonlocal a
... a += 1
... print("before : ".format(a))
... change()
... print ("after : ".format(a))
...
>>> outer(42)
before : 42
after : 43
Python 2 没有 nonlocal
,因此规范的技巧是将变量包装在可变容器中(通常是 list
,但任何可变对象都可以):
>>> def outer(a):
... _a = [a]
... def change():
... _a[0] += 1
... print("before : ".format(_a[0]))
... change()
... print ("after : ".format(_a[0]))
...
>>> outer(42)
before : 42
after : 43
这至少可以说是相当丑陋的。
虽然闭包非常方便,但它们大多是对象的功能对应物:一种在一组函数之间共享状态同时保留该状态封装的方法,所以如果你发现你需要一个 nonlocal
变量也许一个适当的类可能是一个更清洁的解决方案(尽管可能不适用于不返回内部函数但仅在内部使用它的示例)。
【讨论】:
【参考方案2】:我有两个解决方案给你:
#first one:
# try with list, compound data types dict/list
def some_func(a):
def change_a():
a[0] += 1
print(a[0])
change_a()
some_func([1])
>>> 2
#second one
#reference pointer
from ctypes import *
def some_func_ctypes(a):
def change_a():
a[0] += 1
print a.contents, a[0]
change_a()
i = c_int(1)
pi = pointer(i)
some_func_ctypes(pi)
>>> c_int(2) 2
【讨论】:
OP 问的是为什么他可以读取一个非局部变量但不能重新绑定它... @bruno,伙计,你做了很好的解释/回答,谢谢。我应该再解释一遍吗?我想它不再需要,但其他解决方案对未来的读者来说会很棒......【参考方案3】:当您使用+=
运算符时,会为a
分配一个新值。这在口译员的眼中变成了当地人。
【讨论】:
以上是关于外部函数中的嵌套函数更改变量不起作用的主要内容,如果未能解决你的问题,请参考以下文章