什么是闭包?
闭包, 英文为closure.
首先, 闭包是一种特殊的函数. 特殊之处在于它包含了非本地也非全局的自由变量.
def outer_fn():
outer_var = []
def inner_fn(val):
outer_var.append(val)
return sum(outer_var) * 1.0 / len(outer_var)
return inner_fn
在上面的代码中, inner_fn
就是一个闭包函数. 对inner_fn
来说, outer_var
既非它的本地变量, 也非全局变量, 而是outer_fn
的本地变量.
实现原理
按照道理来说, outer_fn
的本地变量在程序退出函数体后会被自动销毁回收, 但因为outer_var
在inner_fn
内被引用了, 所以它不会被销毁, 而是成为一个自由变量. 可是, 在执行inner_fn
的主体代码时, outer_var
存储在哪呢? 在fn
对象的__closure__
属性里:
fn = outer_fn()
print(fn(10))
print ('fn.__closure__:', fn.__closure__[0].cell_contents)
print(fn(20))
print ('fn.__closure__:', fn.__closure__[0].cell_contents)
输出为:
10.0
fn.__closure__: [10]
15.0
fn.__closure__: [10, 20]
有什么用?
也许有用, 例如在修饰器中, 但并非不可缺少. 引入闭包实际是给函数对象引入了状态, 然后呢, 导致相同的输入不一定能得到相同的输出, 感觉有点别扭. 所以, 如果需要保存状态, 可以通过面向对象方式来实现. 例如上面的代码可使用class
封装:
class Cls():
def __init__(self):
self.var = []
def fn(self, val):
self.var.append(val)
return sum(self.var) * 1.0 / len(self.var)
inst = Cls()
print(inst.fn(10))
print(inst.fn(20))
这样虽然可能需要多敲几个字母, 但代码的可维护性大大增加. 所以, 闭包对于我来说, 了解下概念就行, 尽量不用.