我在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()
调用再次导致一个空列表对象。