<p>您可以将生成器转换为协程,这样它们就可以<code>send()</code>并接收彼此的值(使用<code>(yield)</code>表达式)。这将使每个人都有机会更改接收到的值,并/或将它们传递给下一个生成器/协同程序(或完全忽略它们)。在</p>
<p>{I>在下面的示例中使用名为cdi}的coroutine来编写一个名为coroutine的函数。这会导致它们执行到第一个<code>yield</code>表达式/语句之前。这是一个在youtube视频中显示的一个稍作修改的版本,这个视频是davebeazley在pycon2009上发表的一个非常有启发性的演讲,题目是<a href="https://www.youtube.com/watch?v=Z_OAlIhXziw" rel="nofollow noreferrer"><strong>A Curious Course on Coroutines and Concurrency</strong></a>。在</p>
<p>您应该能够从生成的输出中看到,数据值正由通过单个<code>send()</code>配置到头协程的每个管道进行处理,然后头协程将其有效地“多路复用”到每个管道中。由于每个子协程也这样做,所以可以建立一个详细的过程“树”。在</p>
<pre><code>import sys
def coroutine(func):
""" Decorator to "prime" generators used as coroutines. """
def start(*args,**kwargs):
cr = func(*args,**kwargs) # Create coroutine generator function.
next(cr) # Advance to just before its first yield.
return cr
return start
def pipe(name, value, divisor, coroutines):
""" Utility function to send values to list of coroutines. """
print(' {}: {} is divisible by {}'.format(name, value, divisor))
for cr in coroutines:
cr.send(value)
def this_func_name():
""" Helper function that returns name of function calling it. """
frame = sys._getframe(1)
return frame.f_code.co_name
@coroutine
def gen1(*coroutines):
while True:
value = (yield) # Receive values sent here via "send()".
if value % 2 == 0: # Only pipe even values.
pipe(this_func_name(), value, 2, coroutines)
@coroutine
def gen2(*coroutines):
while True:
value = (yield) # Receive values sent here via "send()".
if value % 4 == 0: # Only pipe values divisible by 4.
pipe(this_func_name(), value, 4, coroutines)
@coroutine
def gen3(*coroutines):
while True:
value = (yield) # Receive values sent here via "send()".
if value % 6 == 0: # Only pipe values divisible by 6.
pipe(this_func_name(), value, 6, coroutines)
# Create and link together some coroutine pipelines.
g3 = gen3()
g2 = gen2()
g1 = gen1(g2, g3)
# Send values through both pipelines (g1 -> g2, and g1 -> g3) of coroutines.
for value in range(17):
print('piping {}'.format(value))
g1.send(value)
</code></pre>
<p>输出:</p>
^{pr2}$