是否有理由更喜欢使用map()而不是列表理解,反之亦然?它们中的任何一个通常比另一个更有效或被认为更python化吗?
当前回答
我认为最python化的方法是使用列表理解而不是map和filter。原因是列表推导式比map和filter更清晰。
In [1]: odd_cubes = [x ** 3 for x in range(10) if x % 2 == 1] # using a list comprehension
In [2]: odd_cubes_alt = list(map(lambda x: x ** 3, filter(lambda x: x % 2 == 1, range(10)))) # using map and filter
In [3]: odd_cubes == odd_cubes_alt
Out[3]: True
正如你所看到的,一个理解不需要额外的lambda表达式映射需要。此外,一个理解也允许过滤容易,而映射需要过滤器允许过滤。
其他回答
如果您计划编写任何异步、并行或分布式代码,您可能更喜欢map而不是列表解析——因为大多数异步、并行或分布式包都提供map函数来重载python的map。然后,通过将适当的映射函数传递给代码的其余部分,您可能不必修改原始的串行代码以使其并行运行(等等)。
性能测量
图片来源:Experfy
你可以自己看看在列表理解和映射函数之间哪个更好。
(与map函数相比,列表理解处理100万条记录所需的时间更少。)
在某些情况下,Map可能会快得多(当您没有为此目的而使用lambda,而是在Map和列表推导中使用相同的函数时)。在其他情况下,列表推导式可能更快,大多数(不是所有)python主义者认为它们更直接、更清晰。
当使用完全相同的函数时,map的微小速度优势的例子:
$ python -m timeit -s'xs=range(10)' 'map(hex, xs)'
100000 loops, best of 3: 4.86 usec per loop
$ python -m timeit -s'xs=range(10)' '[hex(x) for x in xs]'
100000 loops, best of 3: 5.58 usec per loop
当map需要lambda时,性能比较完全颠倒的示例:
$ python -m timeit -s'xs=range(10)' 'map(lambda x: x+2, xs)'
100000 loops, best of 3: 4.24 usec per loop
$ python -m timeit -s'xs=range(10)' '[x+2 for x in xs]'
100000 loops, best of 3: 2.32 usec per loop
Python 2:你应该使用map和filter而不是列表推导式。
一个客观的原因是,即使它们不是“Pythonic”,你也应该喜欢它们: 它们需要函数/lambdas作为参数,这引入了一个新的作用域。
我不止一次被这个问题困扰过:
for x, y in somePoints:
# (several lines of code here)
squared = [x ** 2 for x in numbers]
# Oops, x was silently overwritten!
但如果我说:
for x, y in somePoints:
# (several lines of code here)
squared = map(lambda x: x ** 2, numbers)
那一切都会好起来的。
你可以说我在相同的作用域中使用相同的变量名是愚蠢的。
我不是。代码本来是好的——两个x不在同一个作用域内。 直到我将内部块移动到代码的不同部分后,问题才出现(即:问题发生在维护期间,而不是开发期间),而且我没有预料到。
是的,如果你从来没有犯过这个错误,那么列表推导式会更优雅。 但从个人经验(以及看到其他人犯同样的错误)来看,我已经见过很多次这样的情况,所以我认为当这些错误渗透到代码中时,不值得你经历这种痛苦。
结论:
使用映射和过滤器。它们可以防止微妙的、难以诊断的范围相关错误。
注:
不要忘记考虑使用imap和filter(在itertools中),如果它们适合你的情况!
我尝试了@alex-martelli的代码,但发现了一些差异
python -mtimeit -s "xs=range(123456)" "map(hex, xs)"
1000000 loops, best of 5: 218 nsec per loop
python -mtimeit -s "xs=range(123456)" "[hex(x) for x in xs]"
10 loops, best of 5: 19.4 msec per loop
即使对于非常大的范围,Map也需要相同的时间,而从我的代码中可以明显看出,使用列表理解需要花费大量时间。所以除了被认为是“非python的”,我没有遇到任何与map使用有关的性能问题。
推荐文章
- Python中dict对象的联合
- 如何有效地比较两个无序列表(不是集合)?
- 如何在交互式Python中查看整个命令历史?
- 如何显示有两个小数点后的浮点数?
- 如何用OpenCV2.0和Python2.6调整图像大小
- 在每个列表元素上调用int()函数?
- 当使用代码存储库时,如何引用资源的相对路径
- 如何在Flask-SQLAlchemy中按id删除记录
- 在Python中插入列表的第一个位置
- Python Pandas只合并某些列
- 如何在一行中连接两个集而不使用“|”
- 从字符串中移除前缀
- 代码结束时发出警报
- 如何在Python中按字母顺序排序字符串中的字母
- 在matplotlib中将y轴标签添加到次要y轴