python - 什么时候在 python 中销毁本地命名空间?

标签 python python-3.x function

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]())

以上代码的输出是

4
4
4
4
4

我的问题是:在 L=f() 之后,f 的局部命名空间是否被破坏了?如果是这样,函数 n 中的 i 如何与命名空间中的 i 相关联?如果不是,什么时候销毁本地命名空间?

最佳答案

函数调用中有许多“本地” namespace ,它们使您的示例行为正常。具体来说,函数中的变量分为三类:

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

当您调用f 时,Li 是本地名称。当 f 结束时,为 L 创建的对象被传递出函数,但与本地名称 L 的绑定(bind)被销毁。但是,与 i 的绑定(bind)不会被破坏,因为它是一个单元格变量。绑定(bind)存在于 L 的每个元素的 __closure__ 属性中。

如果您查看 L[0].__closure__,您会在其中的一个单元格中找到 iL[1].__closure__ 将引用同一单元格,其中也包含 i。单元格是相同的,因为它来自 f 的相同调用。

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

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

def n(i=i):
    print(i)

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

0
1
2
3
4

关于python - 什么时候在 python 中销毁本地命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69503432/

相关文章:

python - 我们可以添加范围作为从数据库中提取值的标准吗?

JavaScript 函数始终运行底层代码

c - 使用 n 个参数运行函数

Python错误没有那个文件或目录

python - 搜索模式不唯一? - 正则表达式

python - 在Python中查找单词的第一个元音

python - while 循环阻塞异步任务

python - Pandas - 缺少日期的滚动总和

python - Pandas 日期时间减法 - 分配 nan 值

c - "expected expression before char"内部函数