python 中的本地命名空间何时被破坏?

Ryl*_*Liu 3 python function python-3.x

def f():
   L = []
   for i in range(5):
       def n():
           return i
       L.append(n)
   return L

L = f()
print(L[0]())
print(L[1]())
print(L[2]())
print(L[3]())
print(L[4]())
Run Code Online (Sandbox Code Playgroud)

上述代码的输出是

4
4
4
4
4
Run Code Online (Sandbox Code Playgroud)

我的问题是:之后L=f(),本地命名空间是否被f破坏?i如果是这样, in 函数如何ni命名空间关联?如果不是,什么时候本地命名空间会被破坏?

Mad*_*ist 6

函数调用中有许多“本地”命名空间,可以使像您的示例那样的行为正常进行。具体来说,函数中的变量分为三种类型:

  1. 本地:仅在函数中使用。可以返回值,但当函数退出时,与本地名称的绑定将被销毁。Linf就是一个例子。
  2. 单元格:也用于函数和一些嵌套范围。每当调用函数时,都会重新创建这些名称,但之后会作为闭包保留在嵌套作用域中。iinf就是一个例子。
  3. Free:函数中未定义。它们分为两种类型:全局和非全局。全局变量不会被放置在闭包中。相反,它们是通过__globals__函数的属性来访问的。__closure__当封闭的命名空间消失时,非全局变量会保留在属性的单元格中。iinn是非局部自由变量。
  4. 还有内置名称,但我们不讨论这些。

当您拨打fL和时,i都是本地名称。结束时f,为其创建的对象L将从函数中传递出去,但与本地名称的绑定L将被销毁。但是,与 的绑定i不会被破坏,因为它是一个单元变量。绑定存在于__closure__的每个元素的属性中L

如果你看一下L[0].__closure__,你会发现i那里有一个单元格。L[1].__closure__将引用同一单元格,也包含i在其中。该单元格是相同的,因为它来自相同的 调用f

当您n通过 的元素调用时L,会打印 的最后一个值,i因为这是单元格退出时绑定的值f

您可以通过将 的值绑定i为 中的局部变量来获得不同的行为n。例如:

def n(i=i):
    print(i)
Run Code Online (Sandbox Code Playgroud)

现在iinf成为本地的,因为它不再用作非本地的 in n。在 中ni现在是一个局部变量,它从默认参数中获取其值。i默认参数在创建函数对象时绑定,因此将引用创建列表元素时的本地值。这与自由变量形成对比,自由变量在函数运行时在闭包中查找。该版本的输出将是

0
1
2
3
4
Run Code Online (Sandbox Code Playgroud)