Bootstrap

Python:闭包陷阱

闭包会捕获并“记住”它们被创建时的环境,如果不正确理解这一点,可能会产生一些意外的结果。

示例1:

以下代码在r列表中存入函数,试图输出 1 2 3

l=[1,2,3]
r=[]
for a in l:
    r.append(lambda x:x+a)
for f in r:
    print(f(0))

但实际结果为3 3 3

原因:以上写法认为每次向r中存入函数时,a的值会传进去,如当a为1时,认为传入的函数为lambda x :x+1。实则不然,lambda函数体只有在被调用时才求值,以上代码调用函数时a已经变为了3。

解决方案:修改为

r.append(lambda x,t=a:x+t)

在每次存入函数时,对a求值即可

示例2:

lst1=[];lst2=[]
for x in range(3):
    lst1.append(lambda:x)
    lst2.append(lambda t=x:t)
print([f() for f in lst1])
print([f() for f in lst2])

运行结果分别为 [2, 2, 2] 和 [0, 1, 2]

;