前言
闭包的延迟特性常常会在面试中考到,我之前面试也遇到过,虽然早就有所了解,但总是记不住。这里再写出来一下让自己长长记性
闭包的延迟
简而言之就是闭包返回的内层函数不会立即执行
, 而是在使用时候才执行
基于这个特性,内层函数如果使用了循环,同时使用到了循环计数值,则因其延迟特性
,当使用到闭包时循环已经结束,所有的循环都已经结束,得到意料之外的结果
计算函数的执行结果
case1
def func():
return [lambda x: x * i for i in range(5)]
# func return [lambda x: x * 4, lambda x: x * 4, lambda x: x * 4, lambda x: x * 4, lambda x: x * 4]
print("func result:", [m(3) for m in func()])
>>>func result: [12, 12, 12, 12, 12]
# solve this problem: method1
def func2():
return [lambda x, i=i: x * i for i in range(5)]
# func2 return [lambda x: x * 0, lambda x: x * 1, lambda x: x * 2, lambda x: x * 3, lambda x: x * 4]
print("func2 result:", [m(3) for m in func2()])
>>>func2 result: [0, 3, 6, 9, 12]
# solve this problem: method2
def func3():
for i in range(5):
yield lambda x: x * i
print("func3 result:", [m(3) for m in func2()])
>>>func3 result: [0, 3, 6, 9, 12]
case2
def count():
fs = []
for i in range(1, 4):
def c():
return i * i
fs.append(c)
return fs # fs = [c(), c(), c()]
f1, f2, f3 = count() # 调用时i的for循环执行结束,i=3,c()=9
print("f1:", f1())
print("f2:", f2())
print("f3:", f3())
>>>f1: 9
>>>f2: 9
>>>f3: 9
# solve this problem
# 可以再创建一层函数, 加深深度, 以便于将循环变量与函数执行的变量隔开
def count2():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs # fs = [f(1), f(2), f(3)] = [1*1, 2*2, 3*3]
c1, c2, c3 = count2()
print("c1:", c1())
print("c2:", c2())
print("c3:", c3())
>>>c1: 1
>>>c2: 4
>>>c3: 9