Python: 在外部函数 return 之后修改非局部变量

Python: modify nonlocal variable after return from outer function

考虑以下示例:

def g():

    in_g=100

    def f1():
        nonlocal in_g
        in_g = 10

    def f2():
        nonlocal in_g
        print(in_g)

    return (f1,f2)


(f1, f2) = g()

f2() #prints 100
f1()
f2() #prints 10

内部函数 f1f2 在它们的 "closures" 中都可以访问变量 in_g。 但是,greturns之后,in_g在内存中保存在哪里呢?

我假设当 g 正在执行时,in_g 是堆栈帧上的一个变量,对应于对 g 的调用。因此,gf1f2 在使用变量 in_g.

时都访问相同的内存位置(在堆栈上)

但是,如示例所示,在 g returns 之后,f1f2 在引用 in_g 时仍然访问相同的内存位置。然而,现在 g 返回了,那个内存位置不能再在栈上了。

以上代码的输出是 100 & 10 。


因为首先 f2() 调用所以它直接访问 in_g 变量并打印它的值。在 f1() 调用之后它将 in_g 变量值更新为 10。然后 f2( ) 函数再次调用,因此由于非本地语句,它绑定了先前的值,这就是它打印 10 值的原因。


nonlocal 语句 导致列出的标识符引用最近封闭范围内的先前绑定变量,不包括全局变量。这很重要,因为绑定的默认行为是首先搜索本地命名空间。该语句允许封装的代码重新绑定除全局(模块)范围之外的局部范围之外的变量。 与全局语句中列出的名称不同,非局部语句中列出的名称必须引用封闭范围中预先存在的绑定(无法明确确定应在其中创建新绑定的范围)。 非本地语句中列出的名称不得与本地范围内预先存在的绑定冲突。


我相信我在这里找到了答案:http://stupidpythonideas.blogspot.ro/2015/12/how-lookup-works.html

因此,当访问 in_ggf1f2 时,会访问一个 cell variable,后者又持有对实际对象的引用目的。