考虑以下代码:
def g1():
while True:
yield 1
def g2():
while True:
yield 1
yield 2
def g3():
while True:
yield 1
yield 2
yield 3
def G():
# Zip all three generators
genList = [g1(), g2(), g3()]
Z = zip(*genList)
yield from Z
# Iterate over the zip of all three generators
for i, g in zip(range(6), G()):
print(g)
三个生成器g1,g2,g3都生成简单数字,而外部生成器G从这三个生成器的zip生成。输出最终看起来像这样:
(1, 1, 1)
(1, 2, 2)
(1, 1, 3)
(1, 2, 1)
(1, 1, 2)
(1, 2, 3)
这就是我所期望的:这三个生成器是“并发地”迭代的,也就是说,在进入下一个生成器之前,我并没有用尽所有的生成器。
但是,我担心这有点麻烦。它之所以起作用,是因为python中的zip类型实现了该__next__
方法,我认为在遍历G()生成器时会调用该方法。
但是,假设我想将值发送给生成器?IE
# stop iteration if a negative value is sent
def g1():
yield
while True:
input = yield 1
if input < 0:
break
...
# Create the generator and prime it
gen = G()
next(gen)
for i in zip(range(6)):
g = gen.send(1)
print(g)
gen.send(-1)
zip类型没有实现该send
功能,我不确定该如何实现。
应该说,我在生成器,协程以及更重要的yield from
是python中新语法方面的经验非常少。我实际上担心我在不真正了解其用途的情况下试图将这些语言功能塞入我的代码中。
最终,这些功能的目的将是返回一个与音频循环相对应的字符串容器。g1生成器每次都会产生相同的循环,g2生成器将交替生成,依此类推。这些变化将导致每次迭代时返回不同的容器。
将每个循环视为自己的协程似乎是有意义的,因为它独立于其他循环而前进,我想尝试利用某些语言功能,而不是想出一种便携性较低的面向对象的解决方案。
但是,也许itertools中有一些我可以利用的东西,或者有一些使用上下文管理器的东西。
send
只是从yield
完全相同的next
调用中恢复,但传入一个值。如果您使用next
而不是,send
则就像发送None
。
您可以使用它来停止生成器执行:
value = yield x
if value:
return
只要您对其进行遍历(通过zip
,for-loop或next
),它就会一直运行,但是当您send
使用任何真实值时,它就会停止。但是,我想知道为什么你甚至想要。您认为需要在哪里做这样的事情?
还要注意,itertools.cycle
您已经在这里尝试做的事情了:
import itertools
c = itertools.cycle([1, 2, 3])
next(c), next(c), next(c), next(c)
# 1, 2, 3, 1, ...
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句