Python|Python 推导式+lambda

今天在网上看到一个面试题:

def multipliers(): return [lambda x,y=i: y * x for i in range(4)] print [m(2) for m in multipliers()]

【Python|Python 推导式+lambda】本来以为结果会是[0,2,4,6]
输出结果居然为:[6,6,6,6],也真是666.
感觉很神奇百度了一下,大部分都是从闭包角度讲,感觉云里雾里,例如:
https://blog.csdn.net/xie_0723/article/details/53925076这一篇讲的就比较详细。
但是我还是像我这种python新手还是有点难理解。于是我就想从python推导式与lambda方面分析一下。
下面这个例子与上面的面试题例子运行结果一样:
temp =[lambdax :i* x for i in range(4)] print [m(2) for m in temp]

首先temp=[]说明返回的是一个列表,for i in range(4)说明这是一个推导式(推导式的作用就是由一个旧的列表生成一个满足条件的新列表,推导式讲解见本人python推导式),产生的新列表是四个元素都是(lambda x : i*x)的列表。
temp =[lambda x :i* x for i in range(4)]只是声明了这四个匿名函数。
这个新列表目前是:
[(lambda x : i*x),(lambda x : i*x),(lambda x : i*x),(lambda x : i*x)],
只有函数名后面加上()函数才会执行例如上例中的m(2),
这时候新列表就变成了:
[(lambda 2 : i*2),(lambda 2 : i*2),(lambda 2: i*2),(lambda 2 : i*2)],
程序要运行就还要知道i的值,这时候就去找i的值,发现这时候i已经在for循环中变成了3,所以最后输出的结果就是[6,6,6,6]了
那如何让结果变为[0,2,4,6]呢,上面的博客里也给了例子:
def multipliers(): return [lambda x,i=i: i * x for i in range(4)] print [m(2) for m in multipliers()]

这样输出的结果就为[0,2,4,6]了
现在来分析一下这个例子:
同样我们还是先来转换一下;
temp =[lambdax ,i=i:i* x for i in range(4)] print [m(2) for m in temp]

这样其实还是不好理解,再来转换一下:
temp =[lambdax ,y=i:y* x for i in range(4)] print [m(2) for m in temp]

单单看这个匿名函数:lambda x ,y=i:y* x,是不是就是一个求两数之积的匿名函数,并且第二个参数是一个缺省参数,缺省的值为i,同样我们知道参数的缺省值在函数定义的时候就要被指定下来。
那么这就好理解了,在使用推导式声明四个匿名函数的时候,每一个匿名函数要知道自己的缺省值是什么啊,不然到时候怎么去计算,所以for i in range(4)每一个i值都被y保存下来。
temp =[lambda x ,y=i:y* x for i in range(4)]生成的四个匿名函数为:
[(lambda x,y=0 : y*x),(lambda x,y=1 : y*x),(lambda x,y=2 : y*x),(lambda x,y=3 : y*x)]
那结果就顺利成章了 就是[0,2,4,6]。

    推荐阅读