30-高级特性之闭包(2)

1. inner_sum便是一个闭包,他的生命周期和自由变量args一样。

def calc_sum(*args): #可变参数
    def inner_sum():
        ix = 0 #局部变量,暂存累加结果
        for y in args:   #args是calc_sum这个外部函数的变量, 被内部函数{闭包}inner_sum使用了,故args为自由变量
            ix += y
        return ix
    return inner_sum
f = calc_sum(1,2,3,4,5) #此时仅仅返回了inner_sum(), 但并没有激发inner_sum()
print(f,'
') 
res = f()    #调用才激发,懒惰函数
print(res, '
')

2. 每次调用主调函数返回的inner_sum()都是完全不同的,哪怕传入实参相同

f1 = calc_sum(1,2,3,4,5)
f2 = calc_sum(1,2,3,4,5)
print(f1==f2,'
')

3. 注意:因为外部函数返回一个内部函数时,该内部函数并未执行。所以内部函数中不要引用任何可能会变化的变量。

#比如,下面“诡异的异常结果”
def count():
    fs = []
    for i in range(1,4): #[1,4)
        def f():
            return i*i
        fs.append(f)   #把三个f都装入fs,待会儿返回出去
    return fs
f1,f2,f3 = count()
print(f1(), f2(),f3(), '
') #i最终为3,结果三个f()激发的时候都是3*3

#4.防止发生上述的错误,加一层g,并把g(i)绑定for循环的i
def count_2():
    def g(i):                #g是外部函数,不能存在延迟激发
        def f():         #f是内部函数{闭包},会被延迟激发
            return i*i
        return f     #此时返回f,f为闭包
    fs = []
    for i in range(1,4):
        fs.append(g(i))   #g(i)相比较f()而言,为外部函数,立刻执行激发,故把当前的i带入f()
    return fs             #fs压入3个g,相比cout_2而言,g是闭包,g在count_2()时还不会激发
g1,g2,g3 = count_2()
print(g1,'
',g2,'
',g3,'
')
print(g1(), g2(), g3(), '
') #此刻g被激发执行,带动f被激发执行

4. 作业:闭包返回一个计数器

def f():             #f仅仅用来产生递增数据流,可移动至CreateCounter外部,也可以移进去
        n = 1
        while True:
            yield n
            n += 1
def CreateCounter():
    it = f()             #立刻调用f这个generator,f已经产生了所有的递增序列it
    def counter():       #通过counter每次返回it的一个项
        return next(it)   #每次调用只返回it中的一个元素,故而next
    return counter        #把counter返回出去
CountA = CreateCounter() #返回一个counter,但counter没有被激发
print(CountA,'
')

for i in range(5): #5次调用CountA,即每次都激发一下counter,而激发counter的结果就是:next(it),即取一个数
    print(CountA())
原文地址:https://www.cnblogs.com/LS1314/p/8504539.html