我什么时候应该使用Map而不是For Loop?

时间:2009-12-29 15:41:01

标签: python for-loop

这与以下内容有关:(在Python代码中)

for i in object:
     doSomething(i)

map(doSomething, object)

两者都很容易理解,而且很短,但速度有差异吗?现在,如果doSomething有一个返回值,我们需要检查它是否会从map中返回一个列表,而在for循环中我们可以创建自己的列表或一次检查一个。

for i in object:
     returnValue = doSomething(i)
     doSomethingWithReturnValue(returnValue)

returnValue = map(doSomething, object)
map(doSomethingWithReturnValue, returnValue)

现在,我觉得两者有点分歧。两个doSomethingWithReturnValue函数可能会有所不同,因为如果我们在循环中检查它们,或者如果在最后一次检查它们会产生不同的结果。此外,似乎for循环总是有效,也许更慢,地图只能在某些情况下工作。当然,我们可以做出扭曲来使其中任何一种工作,但重点是避免这种工作。

我正在寻找的是一种情况,与完成性能,可读性,可维护性或实施速度的循环相比,映射功能真正发挥作用。如果答案确实没有太大差异那么我想知道在实践中人们何时使用其中一个或者它是否真的完全随意并且根据您的机构通过编码标准设置。

谢谢!

4 个答案:

答案 0 :(得分:27)

当您想要将函数应用于iterable的每个项目并返回结果列表时,

map非常有用。这比使用for循环和构建列表更简单,更简洁。

对于其他情况,

for通常更具可读性,而在lisp中,有许多基本上使用宏和映射编写的迭代结构。因此,如果map不适合,请使用for循环。

理论上,如果我们有一个足够聪明的编译器/解释器来使用多个cpus / processor,那么map可以更快地实现,因为每个项目的不同操作可以并行完成。但是,我认为目前情况并非如此。

答案 1 :(得分:13)

您熟悉timeit模块吗?以下是一些时间安排。 -s执行一次性设置,然后循环命令并记录最佳时间。

1> python -m timeit -s "L=[]; M=range(1000)" "for m in M: L.append(m*2)"
1000 loops, best of 3: 432 usec per loop

2> python -m timeit -s "M=range(1000);f=lambda x: x*2" "L=map(f,M)"
1000 loops, best of 3: 449 usec per loop

3> python -m timeit -s "M=range(1000);f=lambda x:x*2" "L=[f(m) for m in M]"
1000 loops, best of 3: 483 usec per loop

4> python -m timeit -s "L=[]; A=L.append; M=range(1000)" "for m in M: A(m*2)"
1000 loops, best of 3: 287 usec per loop    

5> python -m timeit -s "M=range(1000)" "L=[m*2 for m in M]"
1000 loops, best of 3: 174 usec per loop

注意除最后两个外,它们都是相似的。函数调用(L.append,或f(x))严重影响时序。在#4中,L.append查找已在设置中完成一次。在#5中,使用没有函数调用的列表组合。

答案 2 :(得分:8)

只使用列表推导:它们更加pythonic。它们也具有类似于生成器表达式的语法,这使得从一个表达式切换到另一个表达式变得容易。将代码转换为py3k时,您无需更改任何内容:map返回py3k中的可迭代内容,您必须调整代码。

如果您不关心返回值,只是不要命名新列表,您需要在代码中使用一次返回值,您可能会在最后切换到生成器表达式和单个列表理解。

答案 3 :(得分:-1)

编辑:在python 3.0之后我没有意识到map等于itertools.imap。所以这里的结论可能不正确。我明天将在python 2.6上重新运行测试并发布结果。

如果doSomething非常“小”,map可能比for循环或列表理解快得多:

# Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on win32

from timeit import timeit

do = lambda i: i+1

def _for():
  for i in range(1000):
    do(i)

def _map():
  map(do, range(1000))

def _list():
  [do(i) for i in range(1000)]

timeit(_for, number=10000)  # 2.5515936921388516
timeit(_map, number=10000)  # 0.010167432629884843
timeit(_list, number=10000) # 3.090125159839033

这是因为map是用C语言编写的,而for循环和列表理解是在python虚拟机中运行的。