为什么map在Python 3中返回地图对象而不是列表?
我有兴趣了解Python 3.x的新语言devise 。
我喜欢Python 2.7中的函数map
:
Python 2.7.12 In[2]: map(lambda x: x+1, [1,2,3]) Out[2]: [2, 3, 4]
但是,在Python 3.x中已经发生了变化:
Python 3.5.1 In[2]: map(lambda x: x+1, [1,2,3]) Out[2]: <map at 0x4218390>
我了解如何,但我找不到为什么参考。 语言devise师为什么做这个select,在我看来,这是一个很大的痛苦。 这是为了掰手腕开发者坚持列表parsing吗?
国际海事组织,名单可以自然地认为作为Functors ; 我曾以某种方式被认为这样想:
fmap :: (a -> b) -> fa -> fb
我认为当生成器expression式也存在时,映射依然存在的原因是它可以将多个迭代器参数全部循环并传递给函数:
>>> list(map(min, [1,2,3,4], [0,10,0,10])) [0,2,0,4]
这比使用zip稍微简单一点:
>>> list(min(x, y) for x, y in zip([1,2,3,4], [0,10,0,10]))
否则,它不会在生成器expression式上添加任何内容。
因为它返回一个迭代器,所以省略了将全尺寸列表存储在内存中。 这样你就可以很容易地迭代它,而不会给记忆带来任何痛苦。 可能你甚至不需要一个完整的列表,但它的一部分,直到你的条件达成。
你可以find这个文档有用,迭代器是真棒。
表示数据stream的对象。 重复调用迭代器的
__next__()
方法(或将其传递给内置函数next()
)将返回stream中的连续项。 当没有更多的数据可用时,将引发StopIteration
exception。 此时,迭代器对象已耗尽,并且对__next__()
方法的任何进一步调用都会再次引发StopIteration
。 迭代器需要有一个__iter__()
方法来返回迭代器对象本身,所以每个迭代器也是可迭代的,并且可以在其他迭代器被接受的大多数地方使用。 一个值得注意的例外是尝试多次迭代的代码。 一个容器对象(如list
)会在每次将其传递给iter()
函数或在for循环中使用时产生新的迭代器。 用迭代器试图这样做会返回与前一次迭代中使用的相同的迭代器对象,使其看起来像一个空的容器。
Guido 在这里回答了这个问题:“ 因为创build一个列表将会是浪费 ”。
他还说,正确的转变是使用一个规则for
循环。
将map()
从2转换为3可能不仅仅是一个简单的例子,它围绕着一个list( )
。 圭多还说:
如果input序列的长度不等, map()
会在最短序列的终止处停止,为了与Python 2.x中的map()
完全兼容,也可以将序列封装在itertools.zip_longest()
,例如
map(func, *sequences)
变
list(map(func, itertools.zip_longest(*sequences)))
“
在Python 3中,许多函数(不仅仅是map
, zip
, range
和其他)返回一个迭代器而不是完整的列表。 你可能需要一个迭代器(例如为了避免把整个列表保存在内存中),或者你可能想要一个列表(例如能够索引)。
然而,我认为在Python 3中改变的主要原因是尽pipe使用list(some_iterator)
将迭代器转换为列表是微不足道的,但是反向等价的iter(some_list)
并不能达到期望的结果,因为完整列表已经被build立和记忆。
例如,在Python 3 list(range(n))
工作得很好,因为构buildrange
对象然后将其转换为列表的代价很小。 然而,在Python 2中, iter(range(n))
不会保存任何内存,因为完整列表是在构build迭代器之前由range()
构造的。
因此,在Python 2中,需要单独的函数来创build一个迭代器而不是一个列表,比如map
imap
(尽pipe它们不完全相同 ), range
xrange
, zip
izip
。 相比之下,Python 3只需要一个函数,如果需要, list()
调用将创build完整列表。