her*_*ert 5 python nested python-3.x python-nonlocal
def some_func(a):
def access_a():
print(a)
access_a()
Run Code Online (Sandbox Code Playgroud)
输出 的值a。但是,如果我想像这样更改a嵌套函数:
def some_func(a):
def change_a():
a += 1
print(a)
change_a()
Run Code Online (Sandbox Code Playgroud)
它引发UnboundLocalError异常。
我知道a是一个非局部变量,但为什么我可以在不声明的情况下访问它nonlocal a?
Python 范围规则 101:
local除非明确声明global(Python 2.x 和 3.x)或nonlocal(仅限 Python 3.x),否则会考虑绑定在函数体中的名称。无论赋值发生在函数体的何处,这都适用。在绑定之前尝试读取局部变量当然是错误的。
如果一个名字被读取但没有绑定在函数体中,它将在封闭的作用域(外部函数,如果有的话,然后是全局作用域)中查找。注意:函数参数实际上是本地名称,因此永远不会在封闭范围内查找它们。
请注意,这a += 1主要是 的快捷方式a = a + 1,因此在您的示例中a是本地的(绑定在函数体中,而不是明确声明为全局或非本地的),但是您尝试a = a+1在绑定之前读取它(的 rhs )。
在 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
Run Code Online (Sandbox Code Playgroud)
Python 2 没有,nonlocal所以规范的 hack 是将变量包装在一个可变容器中(通常是一个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
Run Code Online (Sandbox Code Playgroud)
至少可以说这很丑陋。
现在,虽然闭包非常方便,但它们主要是对象的功能对应物:一种在一组函数之间共享状态同时保留此状态的封装的方法,因此,如果您发现需要一个nonlocal变量,那么合适的类可能是一个更清洁的解决方案(尽管可能不适用于您的示例,它不返回内部函数而仅在内部使用它)。
| 归档时间: |
|
| 查看次数: |
2791 次 |
| 最近记录: |