是否有理由更喜欢使用map()而不是列表理解,反之亦然?它们中的任何一个通常比另一个更有效或被认为更python化吗?
当前回答
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中),如果它们适合你的情况!
其他回答
我的用例:
def sum_items(*args):
return sum(args)
list_a = [1, 2, 3]
list_b = [1, 2, 3]
list_of_sums = list(map(sum_items,
list_a, list_b))
>>> [3, 6, 9]
comprehension = [sum(items) for items in iter(zip(list_a, list_b))]
我发现自己开始使用更多的map,我认为map可能比comp慢,因为传递和返回参数,这就是我找到这篇文章的原因。
我相信使用map可以更有可读性和灵活性,特别是当我需要构造列表的值时。
如果你用地图的话,你读的时候就明白了。
def pair_list_items(*args):
return args
packed_list = list(map(pair_list_items,
lista, *listb, listc.....listn))
再加上灵活性奖励。 谢谢你其他的答案,再加上绩效奖金。
我用perfplot(我的一个项目)计算了一些结果。
正如其他人所注意到的,map实际上只返回一个迭代器,因此它是一个常量时间操作。当通过list()实现迭代器时,它与列表推导式相当。根据不同的表达方式,任何一种都可能有轻微的优势,但并不显著。
注意,像x ** 2这样的算术运算在NumPy中要快得多,特别是如果输入数据已经是NumPy数组的话。
hex:
X ** 2:
代码重现图:
import perfplot
def standalone_map(data):
return map(hex, data)
def list_map(data):
return list(map(hex, data))
def comprehension(data):
return [hex(x) for x in data]
b = perfplot.bench(
setup=lambda n: list(range(n)),
kernels=[standalone_map, list_map, comprehension],
n_range=[2 ** k for k in range(20)],
equality_check=None,
)
b.save("out.png")
b.show()
import perfplot
import numpy as np
def standalone_map(data):
return map(lambda x: x ** 2, data[0])
def list_map(data):
return list(map(lambda x: x ** 2, data[0]))
def comprehension(data):
return [x ** 2 for x in data[0]]
def numpy_asarray(data):
return np.asarray(data[0]) ** 2
def numpy_direct(data):
return data[1] ** 2
b = perfplot.bench(
setup=lambda n: (list(range(n)), np.arange(n)),
kernels=[standalone_map, list_map, comprehension, numpy_direct, numpy_asarray],
n_range=[2 ** k for k in range(20)],
equality_check=None,
)
b.save("out2.png")
b.show()
如果您计划编写任何异步、并行或分布式代码,您可能更喜欢map而不是列表解析——因为大多数异步、并行或分布式包都提供map函数来重载python的map。然后,通过将适当的映射函数传递给代码的其余部分,您可能不必修改原始的串行代码以使其并行运行(等等)。
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中),如果它们适合你的情况!
性能测量
图片来源:Experfy
你可以自己看看在列表理解和映射函数之间哪个更好。
(与map函数相比,列表理解处理100万条记录所需的时间更少。)
推荐文章
- python中的assertEquals和assertEqual
- 如何保持Python打印不添加换行符或空格?
- 为什么Python的无穷散列中有π的数字?
- Python 3.7数据类中的类继承
- 如何在PyTorch中初始化权重?
- 计数唯一的值在一列熊猫数据框架像在Qlik?
- 使用Pandas将列转换为行
- 从matplotlib中的颜色映射中获取单个颜色
- 将Pandas或Numpy Nan替换为None以用于MysqlDB
- 使用pandas对同一列进行多个聚合
- 使用Python解析HTML
- django MultiValueDictKeyError错误,我如何处理它
- 如何在for循环期间修改列表条目?
- 我如何在Django中创建一个鼻涕虫?
- 没有名为'django.core.urlresolvers'的模块