协程
Python 协程类似于生成器,但协程主要用作数据使用者,而不是生成数据。换句话说,协程是每次使用 send 方法发送值时恢复的函数。
协程的诀窍是在赋值表达式的右侧使用 yield 关键字。下面是一个协程的示例,它只打印发送到它的值
def coroutine():
print('My coroutine')
while True:
val=yield
print('Got',val)
>>> co = coroutine()
>>> next(co)
My coroutine
>>>co.send(1)
Got 1
>>>co.send(2)
Got 2
>>> co.send(3)
Got 3
需要对 next 进行初始调用才能向前移动协程。
您可以看到它执行了 print 语句。
最终,该函数到达 yield 表达式,它将在其中等待恢复。然后,每次发送值(使用 send)时,协程函数都会从 yield 恢复,将值复制到 val 并打印出来。
协程可以使用 close() 方法关闭。
>>> co.close()
>>> co.send(4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Pipelines
协程可用于实现数据管道,其中一个协程将数据发送到管道中的下一个协程。
协程使用 send() 方法将数据推送到管道中。
下面是一个小管道的示例,其中发送到生产者协程的值被平方并发送到使用者协程进行打印:
def producer(consumer):
print("Producer ready")
while True:
val=yield
consumer.send(val *val)
def consumer():
print("Consumer ready")
while True:
val=yield
print('Consumer got',val)
如上所述,协程必须与 next “启动”,然后才能发送任何值。
>>> cons = consumer()
>>> prod = producer(cons)
>>>next(prod)
Producer ready
>>>next(cons)
Consumer ready
>>>prod.send(1)
Consumer got 1
>>> prod.send(2)
Consumer got 4
>>>prod.send(3)
Consumer got 9
此外,使用协程,可以将数据发送到多个目标。下面的示例实现两个使用者,其中第一个使用者仅打印 0..10 中的数字,第二个使用者仅打印 10..20 中的数字:
def producer(consumers) :
print("Producer ready")
try:
while True:
val= yield
for consumer in consumers:
consumer.send(val * val)
except GeneratorEcit:
for consumer in consumers:
consumer.close()
def consumer(name, low,high):
print("%s ready" % name)
try:
while True:
val =yield
if low < val < high:
print('%s got' % name, val)
except GeneratorExit:
print("%s closed" % name)
和以前一样,在发送任何值之前,必须“启动”协程。
>>>con1 = consumer('Consumer 1', 00,10)
>>> con2 = consumer('Consumer 2', 10,20)
>>> prod = producer([con1,con2])
>>>next(prod)
Producer ready
>>>next(con1)
onsumer 1 ready
>>> next(con2)
Consumer 2 ready
>>>prod.send(1)
Consumer 1 got 1
>>>prod.send(2)
Consumer 1 got 4
>>>prod.send(3)
Consumer 1 got 9
>>>prod.send(4)
Consumer 2 got 16
>>> prod.close()
Consumer 1 closed
Consumer 2 closed
数据被发送到所有使用者,但只有第二个执行 print 语句。
请注意 GeneratorExit 异常的使用。有时,捕获异常并通知下游协程管道不再有用可能很有用。
使用协程管道进行练习
-
实现生产者-消费者管道,其中生产者平方的值将发送给两个消费者。 一个应该存储和打印到目前为止发送的最小值,另一个应该存储和打印最大值。
-
实施生产者-消费者管道,其中生产者平方的值被调度给两个消费者,一次一个。第一个值应发送到使用者 1,第二个值应发送到使用者 2,第三个值应再次发送到使用者 1,依此类推。关闭生产者应该迫使消费者打印一个列表,其中包含每个人获得的数字。