本文共 978 字,大约阅读时间需要 3 分钟。
偶尔看到python的一个经典坑:
flist = [lambda :i for i in range(5)]for f in flist(): print(f())
按照一般逻辑,结果应该是 0 1 2 3 4
但运行结果是44444
查了一下,主要是变量作用域问题和函数执行的问题。
出现这种情况的主要原因是,循环在python中不形成作用域。也就是说,i不仅仅在for循环内有效,for循环结束后i依然可以被使用,即循环结束后,i=4 比如说,如果这样写:flist = [lambda :i for i in range(5)]del iflist[0]()
就会报错
NameError Traceback (most recent call last)in () 1 flist = [lambda :i for i in range(5)]----> 2 del i 3 flist[0]()NameError: name 'i' is not defined
因为把i删除了之后,lambda就没办法找到返回值i了。
然后,只有函数在被调用的时候才运行函数内部的东西,也就是说,在遍历flist的时候,每调用一个f,lambda :i 被执行一次,但记住这时候i=4,所以所有f都返回4。
要想达到预期效果,可以稍微修改一下:
flist = [lambda x=i: x for i in range(5)]for f in flist: print(f())
输出结果
01234
为什么这样就可以了呢?先看下面:
flist=[]for i in range(5): def func(): x = i return x flist.append(func)flist[0]()
输出结果是0。这段代码和上面是等价的。可以看到,i 的值此时被传递进了函数,也就是说,每一个 func 中都有 i值。等到循环结束,flist中的函数元素被调用的时候,因为 i 值在循环的时候已经成了每个func函数中的局部变量,也就是0 1 2 3 4,所以flist=0。
转载地址:http://wwksi.baihongyu.com/