You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数式编程与列表推导等价实现:Mark Lutz示例写法探讨

列表推导的函数式等价写法验证与优化

先看Mark Lutz在《Learning Python》里的这个列表推导示例:

>>> [(x,y) for x in range(5) if x%2==0 for y in range(5) if y%2==1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

我尝试用嵌套的map和filter写出等价的函数式实现,得到的代码是:

>>> list(map(lambda x:list(map(lambda y:(y,x),filter(lambda x:x%2==0,range(5)))), filter(lambda x:x%2==1,range(5))))
[[(0, 1), (2, 1), (4, 1)], [(0, 3), (2, 3), (4, 3)]]

(注:原输出里的...是截断了,实际是嵌套列表)

现在想请教:这个实现是不是原列表推导的正确等价写法?有没有更优的函数式实现方式?


你的实现并不等价,问题出在结构上

先直接说结论:你写的代码不是等价实现。原列表推导的结果是一个扁平的元组列表,但你的代码输出的是嵌套列表——外层是每个奇数y对应的列表,内层是(y,x)的元组(而且元组的顺序还反了,原推导是(x,y),你这里写成了(y,x))。

要对齐原列表推导的逻辑,得先理清楚原推导的执行顺序:

  1. 遍历range(5)里的x,筛选出偶数x
  2. 对每个符合条件的x,遍历range(5)里的y,筛选出奇数y
  3. 把每对(x,y)收集成扁平列表

你的代码刚好把x和y的遍历顺序反过来了,还套了两层列表,所以结构完全不对。

正确的等价函数式写法

要写出和原列表推导完全等价的map+filter实现,需要把嵌套的遍历逻辑转成扁平的迭代,这里可以用itertools.chain来扁平化,或者调整map的嵌套方式:

写法1:用itertools.chain扁平化嵌套map的结果

from itertools import chain

list(chain.from_iterable(
    map(lambda x: map(lambda y: (x, y), filter(lambda y: y % 2 == 1, range(5))),
        filter(lambda x: x % 2 == 0, range(5)))
))

这个代码的逻辑是:

  • 先筛选出偶数x,对每个x,生成对应的奇数y的(x,y)元组迭代器
  • 再用chain.from_iterable把这些迭代器合并成一个扁平的迭代器,最后转成列表,结果和原推导完全一致。

写法2:用嵌套生成器替代部分map(更易读)

如果允许混合生成器表达式(毕竟函数式编程也不排斥生成器),可以写得更简洁:

list((x, y) for x in filter(lambda x: x%2==0, range(5)) for y in filter(lambda y: y%2==1, range(5)))

这其实是把列表推导里的条件换成了filter,逻辑完全对齐原推导,可读性也更好。

更优的函数式实现

如果追求更简洁、更符合Python函数式风格的写法,推荐用itertools.product来生成笛卡尔积,再用filter筛选符合条件的元组:

from itertools import product

list(filter(lambda t: t[0]%2==0 and t[1]%2==1, product(range(5), range(5))))

product(range(5), range(5))会生成所有(x,y)的笛卡尔积,然后filter只保留x是偶数、y是奇数的元组,结果和原推导完全一致,而且代码更简洁直观,性能也不错(因为product是底层优化的迭代器)。


内容的提问来源于stack exchange,提问作者Vladimir Zolotykh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:17:13