2

我有一个演示示例:

def outer(func):

    def inner(foo):   
        arg_inner=some_value     
        func(arg_inner,foo)     

    return inner

 def third_party(arg1,arg2):
     #do something

     final = outer(third_party)
     final(3)

我想知道内部函数如何知道func被调用时的值。内部函数的范围和外部的范围是如何联系起来的?

4

2 回答 2

3

编译器将它们连接起来。

编译outerandinner时,funcin 中的名称outer被标记为闭包,而 .in 中的名称为自由变量inner。在执行时,解释器知道将函数对象的func名称的引用作为闭包单元附加。outerinner

可以在字节码的反汇编中看到结果:

>>> 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_CONSTinner中,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函数对象带有闭包以供以后取消引用。

于 2013-08-08T13:27:02.047 回答
0

查看http://docs.python.org/2/reference/executionmodel.html#naming-and-binding。它包含有关范围的解释。

于 2013-08-08T13:32:36.067 回答