闭包定义
怎么定义
在函数定义中定义内部函数时,如果内部函数引用到了外部域(非global)的对象,我们则称内部函数为闭包,被引用的那个对象(变量)被称为自由变量。闭包是函数式编程中非常重要的概念。
闭包示例
def counter(start_at=0):
count = [start_at]
def incr():
count[0] += 1
return count[0]
return incr
这里incr()
函数就称为闭包,变量count
被称为自由变量。
为何如此定义
我们看看维基百科上的解释就明白了:
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
实现一个简单的闭包
使用上面的例子:
>>> def counter(start_at=0):
count = [start_at]
def incr():
count[0] += 1
return count[0]
return incr
>>> count = counter(5) # 创建一个闭包实例
>>> count() # 调用这个实例
6
>>> count()
7
>>> count()
8
>>> new_count = counter(100) # 创建一个新的闭包实例
>>> new_count()
101
>>> new_count()
102
>>> count()
9
理解闭包的执行过程可以类比类的执行:
创建好闭包实例后,实例会一直存在,除非你显示删除或者程序运行结束。闭包实例就像一个类实例,只不过这个实例里面只有一个函数和n个自由变量。运行一次实例就是调用一下实例里面的函数,会对自由变量进行访问或修改,如果是修改,修改不会随一次调用结束而撤销。
创建好闭包实例之后,创建函数counter()函数
被回收,但内部的自由变量却因为被闭包引用而不会被回收。
注意:
- 上述例子的自由变量
count
没有用一个int型
的数据,而是使用了len=1
的list
,否则会报错。
使用场景
- 用作装饰器。
只不过(不带参数的)装饰器的参数只能是函数。 - 对一些需要重用的功能且不足以定义为类的行为,使用闭包会比使用类占用更少的资源,且更轻巧灵活