闭包与嵌套函数

时间:2018-08-12 12:57:16

标签: python closures

有人可以解释一下,闭包函数和嵌套函数有什么区别?它们都在外部函数内部,但是我没有得到它们之间的区别。

1 个答案:

答案 0 :(得分:4)

没有区别,因为没有关闭函数,实际上不是。有closures,但是该术语指的是保留在外部和内部作用域中使用的变量的技术。剩下的就是嵌套函数

嵌套函数只是在另一个函数内部定义的函数:

def outer():
    def inner():
        # ...
    # ...

outer()定义了inner()的名称时,使用,那么该变量名被称为闭包单元格,存储在闭包中inner的环境:

def outer():
    variable_in_outer = some_value
    another_variable = some_other_value
    def inner():
        expression using variable_in_outer
        # ...
    # ...

此处variable_in_outerinner()封闭,从而创建了一个封闭符。如果inner()的寿命超过outer(例如,由于inner返回了outer()的调用方),那么您就不能清理{{1 }}就像其他局部变量一样。 variable_in_outeranother_variable中嵌套函数未使用的任何其他变量;它只是另一个局部变量,在outer结束时被清除。

因此,创建了一个闭包以“使变量保持活动状态”,直到outer()也消失了。只要inner()需要variable_in_outer闭包单元格,闭包就可以保存inner闭包单元格。

决定关闭哪些名称是在编译时进行的。您可以通过函数对象上的__closure__属性,闭包元组的元组对闭包进行内部检查,每个闭包单元都有一个cell_contents属性,该属性使您可以访问变量的当前值。如果没有关闭,则将__closure__设置为None

>>> def outer():
...     variable_in_outer = 42
...     another_variable = 81
...     def inner():
...         return variable_in_outer
...     return inner  # return the inner function object
...
>>> nested = outer()
>>> nested
<function outer.<locals>.inner at 0x106a46c80>
>>> nested.__closure__
(<cell at 0x1069adfa8: int object at 0x1055adfe0>,)
>>> nested.__closure__[0].cell_contents
42
>>> outer.__closure__ is None  # outer has no closed-over variables.
True

由于编译器决定什么是闭包,什么不是闭包,因此您可以对代码对象进行自省以查看闭包使用了什么名称:

>>> outer.__code__.co_cellvars
('variable_in_outer',)
>>> outer.__code__.co_consts[3]  # code object used to create `inner` functions
<code object inner at 0x106703660, file "<stdin>", line 3>
>>> outer.__code__.co_consts[3].co_freevars
('variable_in_outer',)

co_cellvars是成为闭包的变量的名称,co_freevars是使用这些闭包的引用。