【手撕代码】Python协程实现生产者消费者模型

2020-07-28  本文已影响0人  时间煮菜

什么是协程?

什么是生成器?

生成器定义
为什么需要生成器
创建生成器的两种方法
  1. 将列表生成器的[]改为()**,这样就得到了一个生成器
In [11]: l = [x * x for x in range(5)]

In [12]: l
Out[12]: [0, 1, 4, 9, 16]

In [13]: g = (x * x for x in range(5))

In [14]: g
Out[14]: <generator object <genexpr> at 0x03C76530> 

如打印所示,g使用()创建了generator(生成器)

  1. 只要函数中使用到了yield关键字,那么这个函数就是一个生成器,调用这个函数就会创建一个(generator)对象。
    • 在下面的生产者消费者模型中,我们就使用到了yield协程实现
    • yield相当于return一个值,并且记住这个返回的位置,下一次迭代时,代码从yield的下一条语句开始执行。
    • 可以使用next()来调用生成器对象取值。(用for循环实现迭代)
    • send()和next()一样,都能让生成器继续往下走(遇到yield停),区别在于send()能传一个值,这个值作为yield表达式整体的效果。(也就是send可以强行修改上一个yield表达式值,看下面的栗子感受一下 )
    • next()方法相当于send(None)

第一次next()调用,遇到yield就停,yield返回了i值为0,a没有赋到值;

第二次next()调用,接着yield下面的语句走,打印a,由于a没有赋到值,返回None,i+1, 遇到yield停返回i值为1,a还是没有赋到值

第三次send()调用,send传值“Hello World”,这个send值作为yield表达值整体的效果,也就是强行修改yield i 为 “Hello World” 并且传递给a,a有值了,下面打印a就为 “Hello World” ,i+1,遇到yield停返回i值为2。

In [30]: def test():
    ...:     i = 0
    ...:     while i < 5:
    ...:         a = yield i  # 遇到yield就停
    ...:         print(a)
    ...:         i += 1
    ...:
In [31]: b = test()

In [32]: next(b)
Out[32]: 0

In [33]: next(b)
None
Out[33]: 1

In [34]: b.send(5)
5
Out[34]: 2

In [35]: next(b)
None
Out[35]: 3

关键:下一次迭代,代码从yield的下一条语句开始执行。

下面讲解重点yield实现协程(生产者-消费者)

yield实现生产者-消费者模型

# 消费者
def customer():
    r = ""
    while True:
        n = yield r  # 接受生产者的消息n,并且发送r
        print("customer 接受:", n)
        r = "ok"


# 生产者
def producer(c):
    c.send(None)  # 第一次返回None,不然会报错

    for i in range(6):
        print("开始发送给消费者:", i)
        r = c.send(i)  # 向消费者发送值
        print("接受到消费者:", r)
        print("------------------------")

c=customer()
producer(c)
    

打印效果:

开始发送给消费者: 0
customer 接受: 0
接受到消费者: ok
------------------------
开始发送给消费者: 1
customer 接受: 1
接受到消费者: ok
------------------------
开始发送给消费者: 2
customer 接受: 2
接受到消费者: ok
------------------------
开始发送给消费者: 3
customer 接受: 3
接受到消费者: ok
------------------------
开始发送给消费者: 4
customer 接受: 4
接受到消费者: ok
------------------------
开始发送给消费者: 5
customer 接受: 5
接受到消费者: ok
------------------------

图解过程
上一篇下一篇

猜你喜欢

热点阅读