外部函数中的嵌套函数更改变量不起作用 [英] nested function change variable in an outside function not working
问题描述
def some_func(a):
def access_a():
print(a)
access_a()
输出a
的值.但是,如果我想像这样在嵌套函数中更改a
:
outputs the value of a
. However, if I want to change a
in the nested function like this:
def some_func(a):
def change_a():
a += 1
print(a)
change_a()
它引发UnboundLocalError
异常.
我知道a
是一个非局部变量,但是为什么我可以在不声明nonlocal a
的情况下访问它?
I know a
is a nonlocal variable, but why can I access it without declaring nonlocal a
?
推荐答案
Python作用域规则101:
Python scoping rules 101:
-
在函数主体中绑定的名称被视为
local
,除非明确声明为global
(Python 2.x和3.x)或nonlocal
(仅Python 3.x).无论分配在函数主体中发生什么,这都是正确的.尝试在绑定之前读取局部变量当然是一个错误.
a name bound in a function body is considered
local
unless explicitely declaredglobal
(Python 2.x and 3.x) ornonlocal
(Python 3.x only). This holds true whereever the assignment happens in the function's body. Trying to read a local variable before it's bound is of course an error.
如果名称被读取但未绑定在函数的主体中,则将在封闭的范围(如果有外部范围则为全局范围)中查找该名称.注意:函数参数实际上是本地名称,因此永远不会在范围内查找它们.
if a name is read but not bound in a function's body, it will be looked up in enclosing scopes (outer function(s) if any then global scope). NB: functions arguments are de facto local names so they will never be looked up in enclosing scopes.
请注意,a += 1
主要是a = a + 1
的快捷方式,因此在您的示例中,a
是本地的(绑定在函数主体中,未明确声明为全局或非本地),但是您尝试读取它(rhs a = a+1
)绑定之前.
Note that a += 1
is mainly a shortcut for a = a + 1
, so in your example a
is local (bound in the function's body and not explicitely declared global or nonlocal), but you try to read it (the rhs of a = a+1
) before it's bound.
在Python 3中,您可以使用nonlocal
语句解决此问题:
In Python 3 you can solve this with a nonlocal
statement:
>>> 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
,但任何可变对象都可以):
Python 2 doesn't have nonlocal
so the canonical hack is to wrap the variable in a mutable container (typically a list
but any mutable object would do):
>>> 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
至少可以说这很难看.
which is quite ugly to say the least.
现在,尽管闭包非常方便,但它们大多是对象的功能对应物:一种在一组函数之间共享状态同时保留该状态的封装的方式,因此,如果您发现需要nonlocal
变量也许适当的类可能是更干净的解决方案(尽管对于您的示例而言,可能不返回内部函数,而仅在内部使用它).
Now while closures are quite handy, they are mostly the functional counterpart of objects : a way to share state between a set of functions while preserving encapsulation of this state, so if you find you have a need for a nonlocal
variable perhaps a proper class might be a cleaner solution (though possibly not for your example that doesn't return the inner function but only uses it internally).
这篇关于外部函数中的嵌套函数更改变量不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!