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())