什么是闭包?
简单地说,闭包就是函数和引用环境组成的整体。
在C/C++里,局部变量是分配在栈中的,返回时即出栈释放,而引用变量可以看成是一种环境变量,和函数组合成一个整体,就是闭包。
闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
那么为什么要把引用环境与函数组合起来呢?
这主要是因为在支持嵌套作用域的语言中,有时不能简单直接地确定函数的引用环境。
让我来看Python代码的例子:
def add1():
def add(x):
return x+1
return add
add1Ins = add1()
print(add1Ins(11)) #12
这段代码很好懂吧,我们再来看下面这段代码:
def addA():
A = 11
def add(x):
return x+A
return add
addAIns = add(A)
print(addAIns(11)) #22
这里的A可以看做函数add的环境变量,当add返回时,这个局部变量仍然存在。这里的函数add和其相关的环境变量A组成的实体就是一个闭包。
再来看一个例子:
def line_conf(a, b):
def line(x):
return ax + b
return line
line1 = line_conf(1, 1) #x+1
line2 = line_conf(4, 5) #4x+5
print(line1(5), line2(5)) #6,25
如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。这样,我们就需要更多的参数传递,也减少了代码的可移植性。利用闭包,我们实际上创建了泛函。line函数定义一种广泛意义的函数。随后,可以根据line_conf传递的参数,通过闭包的形式,将最终函数确定下来。
当然还有匿名函数的形式:
def addx(x):
return lambda y: x + y
add8 = addx(8) #8+y
add9 = addx(9) #9+y
print add8(100) #108
print add9(100) #109
一个编程语言需要哪些特性来支持闭包呢,下面列出一些比较重要的条件:
函数是一阶值;
函数可以嵌套定义;
可以捕获引用环境,并把引用环境和函数代码组成一个可调用的实体;
允许定义匿名函数;
这些条件并不是必要的,但具备这些条件能说明一个编程语言对闭包的支持较为完善。
对象是附有行为的数据,而闭包是附有数据的行为。
注意:闭包会使变量始终保存在内存中,如果不当使用会增大内存消耗。
参考:
http://www.ibm.com/developerworks/cn/linux/l-cn-closure/
http://www.cnblogs.com/vamei/archive/2012/12/15/2772451.html