关于Python局部命名空间销毁时机与闭包变量关联的技术问询
Python嵌套函数与局部命名空间的常见疑问
首先先看你给出的代码:
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,接下来针对你的疑问逐一解答:
1. 执行L=f()后,函数f的局部命名空间是否会被销毁?
答案是不会立刻销毁。因为函数f内部定义的嵌套函数n被添加到了列表L中,而这个L又被返回并赋值给了全局变量L。每个n都是一个闭包,它们会持有对f局部作用域的引用——只要还有这样的引用存在,Python的垃圾回收机制就不会回收f的局部命名空间。
2. 若已销毁,内部嵌套函数n中的变量i是如何与f的局部命名空间中的i建立关联的?
这个假设不成立,因为f的局部命名空间并没有被销毁。不过这里可以解释下闭包的核心逻辑:每个n函数并没有在定义时就把i的当前值保存下来,而是保存了一个指向f局部作用域中i变量的引用。当你后续调用L[0]()这类函数时,它会去查找这个引用指向的i的当前值——而循环结束后,i已经被迭代到了4,所以所有n函数返回的都是这个最终值。
3. 若未销毁,Python中的局部命名空间何时才会被销毁?
Python的局部命名空间(也就是函数的局部作用域)会在没有任何外部对象引用它的时候被销毁。举个例子:如果我们执行L = None,那么全局变量L不再引用那个存储了n函数的列表,这些n函数也就没有了被引用的地方,它们对f局部作用域的引用也会随之消失。此时垃圾回收器就会回收f的局部命名空间,释放对应的内存。
另外,如果一个函数执行完成后,没有任何内部定义的对象(比如嵌套函数、内部变量)被外部代码持有引用,那么它的局部命名空间会被立即销毁。
内容的提问来源于stack exchange,提问作者Rylan Liu
相关产品推荐
相关产品推荐

