如何防止迭代器用尽?

如何防止迭代器用尽?,第1张

如何防止迭代器用尽?

无法“重置”生成器。但是,您 可以 使用

itertools.tee
“复制”迭代器。

>>> z = zip(a, b)>>> zip1, zip2 = itertools.tee(z)>>> list(zip1)[(1, 7), (2, 8), (3, 9)]>>> list(zip2)[(1, 7), (2, 8), (3, 9)]

这涉及到缓存值,因此仅当您以大约相同的速率遍历两个可迭代对象时才有意义。(换句话说,不要像我在这里那样使用它!)

另一种方法是传递生成器函数,并在需要迭代时调用它。

def gen(x):    for i in range(x):        yield i ** 2def make_two_lists(gen):    return list(gen()), list(gen())

但是现在,您必须在传递函数时将参数绑定到生成器函数。您可以使用

lambda
它,但是很多人都觉得
lambda
丑陋。(虽然不是我!YMMV。)

>>> make_two_lists(lambda: gen(10))([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], [0, 1, 4, 9, 16, 25, 36, 49, 64, 81])

我希望不用多说,在大多数情况下,最好列出并复制列表。

另外,作为解释此行为的更一般方法,请考虑一下。生成器的作用是生成一系列值,同时在迭代之间保持某种状态。现在,有时,您可能不希望简单地在生成器上进行迭代,而是要执行以下 *** 作:

z = zip(a, b)while some_condition():    fst = next(z, None)    snd = next(z, None)    do_some_things(fst, snd)    if fst is None and snd is None:        do_some_other_things()

假设此循环 可能会可能不会
耗尽

z
。现在,我们的发电机处于不确定状态!因此,在这一点上,必须以明确定义的方式限制生成器的行为。尽管我们不知道生成器在其输出中的位置,但我们知道a)所有后续访问都会在该系列中产生
更高的
值,并且b)一旦它为“空”,我们就可以准确地获得该系列中的所有项目一旦。我们必须具有越多的能力来 *** 纵的状态,就越
z
难以对此进行推理,因此最好避免出现违反这两个诺言的情况。


当然,正如乔尔·科内特(Joel Cornett)在下面指出的那样,
可能编写一个通过该

send
方法接受消息的生成器。并且可以编写可以使用重置的生成器
send
。但是请注意,在这种情况下,
我们所能做的就是发送一条消息 。我们不能直接 *** 纵生成器的状态,因此对生成器状态的所有更改都是定义明确的(通过生成器本身-
假设其编写正确!)。
send
确实是实现协程的,所以我不会将其用于此目的。每天生成器几乎永远不会对发送给它们的值做任何事情-
我认为出于上述原因。



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5616779.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存