编译器将它们连接起来。
编译outer
andinner
时,func
in 中的名称outer
被标记为闭包,而 .in 中的名称为自由变量inner
。在执行时,解释器知道将函数对象的func
名称的引用作为闭包单元附加。outer
inner
可以在字节码的反汇编中看到结果:
>>> import dis
>>> dis.dis(outer)
2 0 LOAD_CLOSURE 0 (func)
3 BUILD_TUPLE 1
6 LOAD_CONST 1 (<code object inner at 0x1079a5ab0, file "<stdin>", line 2>)
9 MAKE_CLOSURE 0
12 STORE_FAST 1 (inner)
4 15 LOAD_FAST 1 (inner)
18 RETURN_VALUE
>>> inner = outer(lambda a, b: None)
>>> dis.dis(inner)
3 0 LOAD_DEREF 0 (func)
3 LOAD_GLOBAL 0 (arg_inner)
6 LOAD_FAST 0 (foo)
9 CALL_FUNCTION 2
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
将名称LOAD_CLOSURE
包装func
在一个闭包中inner
以供使用;构建一个带有附加闭包单元MAKE_CLOSURE
的函数对象(从加载的字节码对象)作为一个元组。LOAD_CONST
在inner
中,LOAD_DEREF
操作码从func
闭包中加载值。
可以在结果inner
函数对象上找到闭包:
>>> inner.func_closure
(<cell at 0x107a25a28: function object at 0x107a28b18>,)
>>> inner.func_code.co_freevars
('func',)
>>> inner.func_closure[0].cell_contents
<function <lambda> at 0x107a28b18>
因此inner
函数对象带有闭包以供以后取消引用。