关于闭包的体会

def calc_sum(lst):
    def lazy_sum():
        return sum(lst)
    return lazy_sum

注意: 发现没法把 lazy_sum 移到 calc_sum 的外部,因为它引用了 calc_sum 的参数 lst。

像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。

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

# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
    fs = []
    for i in range(1, 4): #循环三次
        def f():
             return i*i   #引用了函数外参数
        fs.append(f)      #将f函数逐一添加到fs()中,注意这里并不是把i*i添加进去了,fs()里面添加的是函数,返回函数延迟计算,还没来得及计算i的值
    return fs        #fs()有三个参数,三个参数都是函数

f1, f2, f3 = count()      #count内是一个fs的list函数,有三个元素,f1,f2,f3=[f,f,f],分别一一对应
print(f1(),f2(),f3())      计算f1()的值,此时f()=i*i的i值循环过后已经全部变为3,结算结果为9,9,9

再来看一个小的变动进行对比
# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
    fs = []
    for i in range(1, 4): #循环三次
        def f():
             return i*i   #引用了函数外参数
        fs.append(f())    #注意f()添加到了fs()中,f()是一个计算结果,它已经计算出了i的值,再将它添加到fs[]中
    return fs        #fs()有三个参数,三个参数都是计算结果

f1, f2, f3 = count()      #count内是一个fs的list函数,有三个元素,f1,f2,f3=[f(),f(),f()],分别一一对应,这里f()已经有结果
print(f1,f2,f3)     结算结果为1,4,9

再换一种写法,思路相同

def count():
    fs = []
    for i in range(1, 4):
        def f(j):             #提前定义了一个j变量,目的就是不引起误会,不引用循环变量,既然不是循环变量,它的值就不会变
            def g():
                return j*j
            return g          #f(j)里面返回的是函数,也没有计算j的值,但是j并不是循环变量,所以它的值是唯一的
r = f(i) #每次循环一遍,就将i的值赋值给了j,所以f(j)是确定的 fs.append(r)      #fs()中添加的是函数 return fs f1, f2, f3 = count() print f1(), f2(), f3() #计算结果为1,4,9
 

猜你喜欢

转载自www.cnblogs.com/ncepujie/p/9495930.html