一、定义

闭包(Closure):内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数。

二、举例

1、求一列表(list)中所有元素的和

def calc_sum(lst):
    def lazy_sum():
        return sum(lst)
    return lazy_sum
f = calc_sum([1, 2, 3, 4])  # 调用calc_sum()并没有计算出结果,而是返回函数f
print f()  # 对返回的函数进行调用时,才计算出结果

注:上例说明了返回函数可以把一些计算延迟执行。

2、求一列表(list)中所有元素的积

def calc_prod(lst):
    def lazy_prod():
        def f(x, y):
            return x * y
        return reduce(f, lst, 1)
    return lazy_prod
f = calc_prod([1, 2, 3, 4]) print f()

三、易错点

闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。举例如下:

# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

当count()函数返回了3个函数时,这3个函数所引用的变量 i 的值已经变成了3。由于f1、f2、f3并没有被调用,所以,此时他们并未计算 i*i,当 f1 被调用时:

>>> f1()
9     # 因为f1现在才计算i*i,但现在i的值已经变为3

因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量

 

下面改写count()函数,使其能够正确返回能计算1x1,2x2,3x3的函数。

它可以正确地返回一个闭包g,g所引用的变量x不是循环变量,因此将正常执行。还需要注意,在count函数的循环内部,如果借助g函数,就可以避免引用循环变量i。

 

注:以上内容整理自【慕课网】

posted on 2019-04-01 17:26  小二妮儿  阅读(212)  评论(0)    收藏  举报