python3中map迭代器和list迭代器的区别



我在python3中使用map和list迭代器时遇到了意外行为。在这个MWE中,我首先生成一个地图的地图。然后,我希望每个映射的第一个元素在一个列表中,其余部分在原始映射中:

# s will be be a map of maps
s=[[1,2,3],[4,5,6]]
s=map(lambda l: map(lambda t:t,l),s)
# uncomment to obtain desired output
# s = list(s) # s is now a list of maps
s1 = map(next,s)
print(list(s1))
print(list(map(list,s)))

在python 3.4.2中运行MWE会得到s1的预期输出:

s1 = ([1,4]),

,但对于s来说是空列表[]。取消注释标记行会产生正确的输出s1,如上所述,但对于s来说也是预期的输出:

s=[[2,3],[5,6]].

文档说map需要一个可迭代对象。直到今天,我还没有看到map迭代器和list迭代器之间的区别。有人能解释一下这种行为吗?

PS:奇怪的是,如果我取消第一个print语句的注释,s的初始状态将被打印出来。所以,这种行为也可能与一种对地图的惰性评估有关?

map()是迭代器;您只能对它迭代一次。例如,您可以使用next()获得单个元素,但是一旦耗尽了项目,您就无法获得任何更多的值。

我给你的对象取了几个容易记住的名字:

>>> s = [[1, 2, 3], [4, 5, 6]]
>>> map_of_maps = map(lambda l: map(lambda t: t, l), s)
>>> first_elements = map(next, map_of_maps)

在这里迭代first_elements将依次迭代map_of_maps。你只能做一次,所以一旦元素用完,任何进一步的迭代都将失败:

>>> next(first_elements)
1
>>> next(first_elements)
4
>>> next(first_elements)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

list()做完全相同的事情;它接受一个可迭代参数,并将迭代该对象以根据结果创建一个新的列表对象。但是,如果您给它一个已经耗尽的map() ,则没有什么可以复制到新列表中了。因此,您将得到一个空结果:

>>> list(first_elements)
[]

您需要从头重新创建map():

>>> map_of_maps = map(lambda l: map(lambda t: t, l), s)
>>> first_elements = map(next, map_of_maps)
>>> list(first_elements)
[1, 4]
>>> list(first_elements)
[]

注意,对map()对象的第二个 list()调用再次导致一个空列表对象。

最新更新