lambda复合生成列表

源代码如下:

1
2
3
4
5
6
7
8
def num():
return [lambda x:i*x for i in range(3)]

a = [m(2) for m in num()]
print(a)

>>>
[4, 4, 4]

函数中返回了一个lambda函数,并且使用了生成列表进行调用函数,生成三个4,具体原因需要一步步进行剖析。

为什么会生成三个,对函数进行for循环到底有什么用?

修改代码如下:

1
2
3
4
5
6
7
8
9
10
def num():
return [lambda x:i*x for i in range(3)]

for m in num():
print(m)

>>>
<function num.<locals>.<listcomp>.<lambda> at 0x00000217771D3D90>
<function num.<locals>.<listcomp>.<lambda> at 0x00000217771D3E18>
<function num.<locals>.<listcomp>.<lambda> at 0x00000217771D3EA0>

发现对函数进行for循环返回三个内存地址不同的返回值,判定和range(3)有关系

1
2
3
4
5
6
7
8
def num():
return [lambda x:i*x for i in range(1)]

for m in num():
print(m)

>>>
<function num.<locals>.<listcomp>.<lambda> at 0x0000011C3EA73D90>

确实有range控制,所以生成列表是生成三个数

为什么全部是4,猜测也和range有关,m(2)传入2参数是给lambda参数x的,所以4是由i*x产生,全部是4应该是range(3)的原因它最大是2,二乘二得4,下面只需改一个数进行验证。

1
2
3
4
5
6
7
8
def num():
return [lambda x:i*x for i in range(4)] #将3改成4

a = [m(2) for m in num()]
print(a)

>>>
[6, 6, 6, 6]

发现由4变成6,推断正确,range(4)最大是3,三乘二得六,都是以最后一个作为返回值。

全部都返回一个数的原因:

1
2
3
4
5
a = [lambda x:x*i for i in range(3)]
print(a)

>>>
[<function <listcomp>.<lambda> at 0x00000288BD48C268>, <function <listcomp>.<lambda> at 0x00000288BDE24D90>, <function <listcomp>.<lambda> at 0x00000288BDE24E18>, <function <listcomp>.<lambda> at 0x00000288BDE24EA0>]

直接生成四个函数,由此可见for m in num()只不过是对这个列表进行遍历。然后再将参数传入每个函数再生成一个列表。此时所有的i都已经是3了。

使用如下改法可以产生不同效果:

1
2
3
4
5
6
7
8
def num():
return [lambda x:[i*x for i in range(3)]]

a = [m(2) for m in num()]
print(a)

>>>
[[0, 2, 4]]