闭包的概念:
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
在通过Python的语言介绍一下,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。你在调用函数A的时候传递的参数就是自由变量。
def func(name):
def inner_func(age):
print 'name:', name, 'age:', age
return inner_func
bb = func('the5fire')
bb(26) # >>> name: the5fire age: 26
这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收。
我们再来看一个平时使用时容易上当的例子:
def A():
return [lambda x : i * x for i in range(4)]
print [m(2) for m in A()] #>>> [6, 6, 6, 6]
def B():
return [lambda x, y = i : y * x for i in range(4)]
print [m(2) for m in B()] #>>> [0, 2, 4, 6]
我们看到第一个函数得到的结果并非我们想要的[0,2,4,6],这里就牵扯到了闭包和自由变量的问题。函数A和B返回了函数,所以产生了闭包,i都是闭包中的自由变量。当print调用A返回的函数对象时,函数中会用到闭包中的自由变量。由于A函数先生成了4个函数,再调用函数列表中的第一个函数,所以当第一个函数被调用时,闭包中的i已经成为3,所以四个函数执行时i都已变成3。函数B的不同点在于闭包中的自由变量先传给了参数y作为默认参数。我们知道函数对象产生时它的默认参数已经保存在该函数对象中,所以B中的自由变量i只在B第一次被调用生成4个函数对象时用到,那时构造4个函数时的i分别是0,1,2,3。print中返回的函数执行时没有再用到闭包中的i,而是调用默认参数。