提到Closure(闭包),大家会联想到JavaScript,但实际上Python也是支持它的,尽管不十分常见,但是Closure的确也是Python一个十分重要的组成。Closure,或者说factory function,本质上来说是一段作用域,在这个作用域中保存着其中的变量的状态。看下面一段代码
-
def func(x):
-
action = (lambda n: x ** n)
-
return action
-
-
action = func(3)
-
我们首先定义额一个函数func,在其中定义一个变量action,其值是一个lambda表达式(匿名函数) x ** n,也就是x的n次方,然后返回action。接下来把func(3)赋值给action,那么现在action等于什么呢?答案是3 ** n,因此如下语句将返回9。
如果是C/C++的程序员看到这会很疑惑,一个函数结束调用以后,其中的变量就应该被回收掉了,可是这里很明显func(3)结束调用以后其内部的x值一直都保留为3,这到底是为什么呢?因为Python中的函数其实就是一个对象,def的作用不过是创建一个对象然后赋给这个函数名而已。
不过在Closure的使用上一不小心就会犯错,看下面这个例子,
-
def makeActions():
-
acts = []
-
for i in range(5):
-
acts.append(lambda x: i ** x)
-
return acts
-
acts = makeActions()
这段代码师徒在makeActions的函数中返回一个acts,这个acts是一个长度是5的数组,数组的每一个元素是一个匿名函数表达式,即从0至4的x次幂。可是结果却出人意料,实际上不论acts[0](2)还是acts[4](2)都返回16,即4的平方。出现这种情况的原因是:Closure内部的变量的值只有在内部定义的函数也就是acts被调用的时候才会被确定,因此不论acts[0]还是acts[4]他们内部的i值都是循环结束时的值4。
要解决这个问题,我们需要利用函数的默认参数来显示的把内部参数的值固定,原因是默认参数的值是在函数创建的那一刻确定的,
-
def makeActions():
-
acts = []
-
for i in range(5):
-
acts.append(lambda x, i=i: i ** x)
-
return acts
-
acts = makeActions()
这样acts[0](2)就是0,act[4](2)的值就是16了。
阅读(1630) | 评论(0) | 转发(0) |