是否有理由更喜欢使用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表达式映射需要。此外,一个理解也允许过滤容易,而映射需要过滤器允许过滤。

其他回答

实际上,在Python 3语言中,map和list推导式的行为非常不同。看一下下面的Python 3程序:

def square(x):
    return x*x
squares = map(square, [1, 2, 3])
print(list(squares))
print(list(squares))

你可能希望它打印“[1,4,9]”这一行两次,但实际上它打印的是“[1,4,9]”后面跟着“[]”。当你第一次看到正方形时,它似乎表现为一个由三个元素组成的序列,但第二次则是一个空的序列。

在Python 2语言中,map返回一个普通的旧列表,就像两种语言中的列表推导一样。关键是Python 3中的map(以及Python 2中的imap)的返回值不是一个列表——它是一个迭代器!

与遍历列表不同,元素是在遍历迭代器时使用的。这就是为什么在最后一个print(list(squares))行中squares看起来是空的。

总结:

在处理迭代器时,必须记住它们是有状态的,并且在遍历时发生变化。 列表更容易预测,因为只有当你显式地改变它们时,它们才会改变;它们是容器。 还有一个好处:数字、字符串和元组甚至更可预测,因为它们根本不能改变;它们是价值观。

这里有一个可能的例子:

map(lambda op1,op2: op1*op2, list1, list2)

对比:

[op1*op2 for op1,op2 in zip(list1,list2)]

我猜,如果坚持使用列表推导式而不是映射,那么zip()是一种不幸的、不必要的开销。如果有人能肯定或否定地澄清这一点,那就太好了。

我的用例:

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))

再加上灵活性奖励。 谢谢你其他的答案,再加上绩效奖金。

性能测量

图片来源:Experfy

你可以自己看看在列表理解和映射函数之间哪个更好。

(与map函数相比,列表理解处理100万条记录所需的时间更少。)

我认为最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表达式映射需要。此外,一个理解也允许过滤容易,而映射需要过滤器允许过滤。