对Python协程的一点理解

参考廖雪峰的Python教程-协程

参照教程利用协程实现的一个很简单的"生产者-消费者"模型如下:

import time

def consumer():
    r = ''
    count = 0
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        count += 1
        print('Consumer count: %s' % count)
        time.sleep(5)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 3:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()
produce(c)

执行结果如下

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
Consumer count: 1
# wait 5 secs
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
Consumer count: 2
# wait 5 secs
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
Consumer count: 3
# wait 5 secs
[PRODUCER] Consumer return: 200 OK

在这个例子里,consumer是一个生成器,produce是被执行的主程序,通过形如generator.send(value)的方法去调用生成器。生成器的每一次被调用,都会向下执行直到yield为止。

我们可以看到Comsumer count每一次的值都不一样,生成器每一次yield返回值时,虽然程序的执行切回了主程序,但是生成器中的整个环境(局部变量等)都被保存了起来,当下次再被调用时再被复原,就好像生成器接续上次继续执行一样。

关于send函数

官方文档对send函数的解释如下

Resumes the execution and “sends” a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value.

也就是说,send函数是用来向生成器传值,并且获取生成器yield的值的。

一般来讲,在正式send值给生成器之前要先send一个空值,这是为了让生成器的代码向下执行,进入While Ture循环。

n = yield r这行代码在生成器非第一次被调用的时候,会分两次执行

  1. 接受send函数传入的值
  2. 继续向下执行,在下一次的循环中执行到这里的时候yield r返回r值。
posted @ 2018-06-30 15:18  Joseph_Chuh  阅读(116)  评论(0编辑  收藏  举报