如何在Iterable中包装Iterator以便以pythonic方式重复使用?

时间:2019-01-17 14:47:02

标签: python iterator iterable

简介

我有一个迭代器,例如:

from itertools import product

iterator_ = product([1, 2, 3], [7, 8, 9])

如果我尝试对迭代器进行多次迭代,那么我将无法执行,因为在完成第一次迭代后就用尽了。

问题

如何从iterable_生成可迭代的iterator_,以便可以根据需要在迭代器上进行多次迭代?最好是一种有效的Python方式。

丑陋的解决方案/示例

它不适用于所有迭代器-查看评论

到目前为止,我能够提出以下丑陋的解决方案:

from copy import copy
from typing import Iterable, Iterator


class WrappedIterator(Iterable):
    """
    Wraps an iterator in an iterable

    This allows to iterate over a given iterator more than once. Subsequent
    actions on the given iterator do not have impact due to internal copying.
    """

    def __init__(self, iterator: Iterator):
        self._iterator = copy(iterator)

    def __iter__(self) -> Iterator:
        return copy(self._iterator)

    def __next__(self):
        raise NotImplementedError(
            "One is not supposed to iterate over this object. Instead, "
            "one should produce an iterator from it with `__iter__` and "
            "iterate (as in, call `__next__` on the returned iterator).")

因此,以下内容使我可以从迭代器中创建一个可迭代的对象:

iterable_ = WrappedIterator(iterator_)

# The following does not fail
for _ in range(666):
    assert len(list(iterable_)) > 0

# The following fails on attempt number 1
for i in range(666):
    assert len(list(iterator_)) > 0, f"Failed on attempt {i}"

其他想法

我在itertools.teeitertools.zip上看到了一些帖子,但是我不确定这些解决方案是否足够高效且具有Python风格。但是我可以肯定他们是错的。

0 个答案:

没有答案