我目前正在阅读 Python 3.5 的官方文档。
它指出 range()
是可迭代的,而 list()
和 for
是迭代器。 [section 4.3]
然而,here它声明 zip()
生成了一个迭代器。
我的问题是,当我们使用这条指令时:
list(zip(list1, list2))
我们是否使用迭代器 (list()
) 来迭代另一个迭代器?
最佳答案
文档在这里通过重新使用术语“迭代器”造成了一些困惑。
iterator protocol 包含三个组成部分:
可迭代对象;您可以可能迭代并逐一获取其元素的事物。
迭代器;进行迭代的事情。每次你想遍历一个可迭代对象的所有项目时,你都需要其中一个来跟踪你在这个过程中的位置。这些不可重复使用;一旦你到达终点,就是这样。对于大多数可迭代对象,您可以创建多个独立的迭代器,每个迭代器独立跟踪位置。
迭代器的消费者;那些想要对元素做些什么的人。
for
循环是后者的一个例子,所以#3。 for
循环使用 iter()
function为您想要循环的任何内容生成一个迭代器(上面的#2),因此“whatever”必须是可迭代的(上面的#1)。
range()
是#1 的例子;它是可迭代的对象。您可以独立地对其进行多次迭代:
>>> r = range(5)
>>> r_iter_1 = iter(r)
>>> next(r_iter_1)
0
>>> next(r_iter_1)
1
>>> r_iter_2 = iter(r)
>>> next(r_iter_2)
0
>>> next(r_iter_1)
2
此处 r_iter_1
和 r_iter_2
是两个独立的迭代器,每次您请求下一个项目时,它们都会根据自己的内部簿记进行操作。
list()
是可迭代对象 (#1) 和迭代消费者 (#3) 的示例。如果将另一个可迭代对象 (#1) 传递给 list()
调用,则会生成一个包含该可迭代对象中所有元素的列表对象。但是列表对象本身也是可迭代的。
zip()
,在 Python 3 中,接收多个可迭代对象 (#1),并且它本身是一个迭代器 (#2)。 zip()
为您提供的每个可迭代对象存储一个新的迭代器 (#2)。每次您向 zip()
请求下一个元素时,zip()
都会使用来自每个包含的可迭代对象的下一个元素构建一个新元组:
>>> lst1, lst2 = ['foo', 'bar'], [42, 81]
>>> zipit = zip(lst1, lst2)
>>> next(zipit)
('foo', 42)
>>> next(zipit)
('bar', 81)
所以最后,list(zip(list1, list2))
同时使用 list1
和 list2
作为迭代(#1),当 zip()
本身被外部 list()
调用消耗时,它会消耗那些 (#3)。
关于python - 关于 Python 中迭代器和可迭代对象的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40650082/