python 闭包什么时候进行捕获?

When python closures are exactly doing their capture?

这是 python 中的一个相当不言自明的代码片段:

globl = 1
def foo():
    def bar(): 
        return free+capture
    capture = globl #not seen, when bar is defined
    return bar

free = 2
a = foo()
globl = 4
b = foo()
print(a()) #3
print(b()) #6
print(a.__closure__[0].cell_contents) # 1
print(b.__closure__[0].cell_contents) # 4 

定义'bar'时,'free'和'captured'变量都是自由的。它们不存在于父环境中,也不存在于根目录中。当从 'foo' 编辑 'bar' return 时,将捕获 'capture'。来自堆栈!
所以我假设 python 在函数的 return 上关闭环境。为什么会这样?为什么不在 'bar' 的定义时间? 如果我们将 bar 替换为 lambda:

,同样的代码片段也有效
bar = lambda : free+capture

在编译时,当python遇到一个函数时,它会做出一些判断。它查看函数中的所有内容,它不会创建作用域或命名空间,但会确定哪些变量将是局部变量或非局部变量。

当您 运行 foo() 时,这意味着在 foo 的 运行 时间,bar 函数被创建并且 python 确定“免费" 和 "capture" 作为非局部变量,因此 bar 已经引用了自由变量。

“free”和“capture”在两个不同的范围内,但始终引用相同的“值”。当python确定“bar”的局部变量时,它创建一个单元格对象。

所以当外部函数“foo”完成运行ning 时,这个“Cell”对象仍然存在,所以当调用内部函数“bar”时,它仍然得到相同的值。