为什么我不能对同一个迭代器进行两次迭代?如何“重置”迭代器或重用数据?

2024-03-08

考虑代码:

def test(data):
    for row in data:
        print("first loop")
    for row in data:
        print("second loop")

When data is an iterator https://docs.python.org/3/glossary.html#term-iterator, for example a list iterator or a generator expression*, this does not work:

>>> test(iter([1, 2]))
first loop
first loop
>>> test((_ for _ in [1, 2]))
first loop
first loop

这打印first loop有几次,自从data是非空的。然而,它确实not print second loop. 为什么会迭代data第一次工作,但第二次就不行了?我怎样才能让它第二次工作?

除了for循环,任何类型的迭代都会出现同样的问题:列表/集合/字典理解,将迭代器传递给list(), sum() or reduce(), etc.

另一方面,如果data是另一种iterable https://docs.python.org/3/glossary.html#term-iterable, 比如一个list or a range(两者都是序列 https://docs.python.org/3/glossary.html#term-sequence),两个循环都按预期运行:

>>> test([1, 2])
first loop
first loop
second loop
second loop
>>> test(range(2))
first loop
first loop
second loop
second loop

* 更多示例:

  • 文件对象 https://stackoverflow.com/questions/3906137
  • 从显式生成器函数创建的生成器 https://stackoverflow.com/questions/1271320
  • filter https://stackoverflow.com/questions/44420135, map https://stackoverflow.com/questions/36486950, and zip https://stackoverflow.com/questions/31683959对象(3.x 中)
  • enumerate objects https://stackoverflow.com/questions/23663231
  • csv.readers https://stackoverflow.com/questions/6755460
  • 中定义的各种迭代器itertools https://docs.python.org/3/library/itertools.html标准库

For general theory and terminology explanation, see What are iterator, iterable, and iteration? https://stackoverflow.com/questions/9884132.

To detect whether the input is an iterator or a "reusable" iterable, see Ensure that an argument can be iterated twice https://stackoverflow.com/questions/70381559.


迭代器只能被使用一次。例如:

lst = [1, 2, 3]
it = iter(lst)

next(it)
# => 1
next(it)
# => 2
next(it)
# => 3
next(it)
# => StopIteration

当迭代器被提供给for而是循环,最后一个StopIteration会导致它第一次退出。尝试在另一个 for 循环中使用相同的迭代器将导致StopIteration立即再次执行,因为迭代器已被消耗。

解决这个问题的一个简单方法是将所有元素保存到一个列表中,可以根据需要多次遍历该列表。例如:

data = list(data)

但是,如果迭代器要迭代许多元素,则最好使用以下命令创建独立迭代器tee() https://docs.python.org/library/itertools.html#itertools.tee:

import itertools
it1, it2 = itertools.tee(data, 2) # create as many as needed

现在可以依次迭代每个:

for e in it1:
    print("first loop")

for e in it2:
    print("second loop")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我不能对同一个迭代器进行两次迭代?如何“重置”迭代器或重用数据? 的相关文章

随机推荐