有人可以解释一下,闭包函数和嵌套函数有什么区别?它们都在外部函数内部,但是我没有得到它们之间的区别。
答案 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_outer
被inner()
封闭,从而创建了一个封闭符。如果inner()
的寿命超过outer
(例如,由于inner
返回了outer()
的调用方),那么您就不能清理{{1 }}就像其他局部变量一样。 variable_in_outer
是another_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
是使用这些闭包的引用。