重复使用生成器的最佳Pythonic方法是什么?

5

我有两个具有以下签名的生成器:

  • gen1(inputs) -> Iterator[A]
  • gen2(Iterator[A]) -> Iterator[B]

我的目标是编写另一个生成器(我们称之为final_gen),它可以给出AB

然而,如果我将gen1gen2链接在一起,如下所示:

def final_gen(inputs):
    yield from gen2(gen1(inputs))

gen1 将被消耗,我无法获取 A

想知道在 Python 中 “重用” gen1 的方式是什么?

更新 我能想到几种方法,但都不满意

  1. gen1 收集到元组或列表中,以便使用这些值。这样会浪费内存。
  2. 使用 itertools.tee 创建 gen1 的克隆。然而,这会浪费计算资源。

5
我理解你想寻找另一种方法的愿望,但我认为你已经成功地列出了唯一两种实现方式。要么将迭代器转换为可迭代对象(最常见的是listtuple),要么使用tee函数将其分成两个独立的生成器。 - Silvio Mayolo
gen2 是否进行表格化/累加/幂等操作?您可以将它们逐个传递给 gen2(gen1(inputs) 中的每个项目 gen2(item))。为什么它们是生成器?与函数有何区别? - John Mee
我猜我可以这样做:((next(gen2([item])), item) for item in gen1(inputs))。在传递给 gen2 之前,我需要将 item 包装成一个列表,并调用 next,以遵循 gen2 的签名。 - Hongtao Yang
@JohnMee 它们是生成器,因为项目列表很长,我想利用它的惰性。 - Hongtao Yang
1个回答

1
我考虑结合使用itertools.tee()来复制你的输入,然后将其封装到另一个函数中,返回两个生成器链的结果。以下是类似于此的代码(在itertools的示例中找到)。
def partition(pred, iterable):
    "Use a predicate to partition entries into false entries and true entries"
    # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
    t1, t2 = tee(iterable)
    return filterfalse(pred, t1), filter(pred, t2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接