itertools.imap vs映射整个iterable

时间:2013-12-31 16:20:08

标签: python python-2.x itertools

我对来自http://docs.python.org/2/library/itertools.html#itertools.imap的陈述感到好奇,即它描述了

sum(imap(operator.mul, vector1, vector2))

作为有效的点积。我的理解是imap给出了一个生成器而不是一个列表,虽然我理解如果你只考虑前几个元素,周围的sum(),它会更快/消耗更少的内存,我不知道如何它的表现与以下不同:

sum(map(operator.mul, vector1, vector2))

4 个答案:

答案 0 :(得分:17)

当您开始增加迭代次数时,mapimap之间的区别变得清晰:

# xrange object, takes up no memory
data = xrange(1000000000)

# Tries to builds a list of 1 billion elements!
# Therefore, fails with MemoryError on 32-bit systems.
doubled = map(lambda x: x * 2, data)

# Generator object that lazily doubles each item as it's iterated over.
# Takes up very little (and constant, independent of data's size) memory.
iter_doubled = itertools.imap(lambda x: x * 2, data)

# This is where the iteration and the doubling happen.
# Again, since no list is created, this doesn't run you out of memory.
sum(iter_doubled)

# (The result is 999999999000000000L, if you're interested.
# It takes a minute or two to compute, but consumes minimal memory.)

请注意,在Python 3中,内置map的行为类似于Python 2的itertools.imap(因为不再需要它而被删除)。要获得“旧的map”行为,您需要使用list(map(...)),这是另一种可视化Python 2的itertools.imapmap彼此不同的好方法。< / p>

答案 1 :(得分:7)

第一行将逐个计算累计项目的总和。第二个将首先计算整个点积,然后,将整个结果存储在内存中,它将继续计算总和。因此存在内存复杂性增益。

答案 2 :(得分:3)

另外需要注意的是“使用更少的内存”通常意味着“运行速度更快”。惰性(迭代器)版本在计算后立即使用每个产品,并将其添加到运行总和中。产品和运行总和几乎肯定都在L1缓存中。如果你首先计算所有产品,那么根据元素的数量,确定计算出的第一批产品将从L1缓存中踢出,然后从L2缓存中取出,并且...当第二次传递时最后将它们加在一起,所有产品在内存层次结构中都很低(而且极端情况下,必须从分页文件中读取)。

但我不清楚你的意思是“不要看它的表现如何与”不同。最终的计算结果都是相同的。

答案 3 :(得分:2)

不同之处在于imap(...)map(...)的整个输出都会传递给sum()。你写的是imap返回一个生成器,但我认为你可能会认为sum(map(...))有一些做同样事情的快捷方式。它没有。在将任何内容传递给map()之前,sum()将构建一个完整的结果列表