无法“重置”生成器。但是,您 可以 使用
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确实是实现协程的,所以我不会将其用于此目的。每天生成器几乎永远不会对发送给它们的值做任何事情-
我认为出于上述原因。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)