python - 外部函数中的嵌套函数更改变量不起作用

标签 python python-3.x nested python-nonlocal

<分区>

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 的情况下访问它?

最佳答案

Python 作用域规则 101:

  1. 函数体中绑定(bind)的名称被视为本地,除非明确声明为global(Python 2.x 和 3.x)或非本地(仅限 Python 3.x)。无论赋值发生在函数体中的什么地方,这都适用。在绑定(bind)之前尝试读取局部变量当然是错误的。

  2. 如果一个名称被读取但未绑定(bind)在函数体中,它将在封闭范围(如果有则为全局范围的外部函数)中查找。注意:函数参数实际上是本地名称,因此永远不会在封闭范围内查找它们。

请注意 a += 1 主要是 a = a + 1 的快捷方式,因此在您的示例中 a 是本地的(绑定(bind)在函数的主体中并且没有明确声明为全局或非本地),但您尝试在绑定(bind)之前读取它(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 所以规范的 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

至少可以说这是相当丑陋的。

虽然闭包非常方便,但它们主要是对象的功能对应物:一种在一组函数之间共享状态同时保留此状态封装的方法,因此如果您发现需要 nonlocal 变量也许一个适当的类可能是一个更清晰的解决方案(尽管对于您的示例可能不返回内部函数但仅在内部使用它)。

关于python - 外部函数中的嵌套函数更改变量不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41278818/

相关文章:

python - 无法更新 Flask 中具有多对多关系的条目

python - 为 Python 模块组合 Windows 安装程序

java - 三角形的嵌套 for 循环

java - Java 中的模块化 : top level vs. 嵌套类

python - 获取父shell的路径

arrays - 如何在 Oracle 中最好地存储数组?

python - Apache Beam 每用户 session 窗口未合并

python - 使用多处理时 pexpect 运行失败

python - Jupyter Lab 中针对包 pycwt 的 ModuleNotFoundError

python - Unicode解码错误: 'ascii' codec can't decode byte 0xf0 in position 6233: ordinal not in range(128)