用yield实现python协程

时间:2023-11-24 15:32:44

刚刚介绍了pythonyield关键字,趁热打铁,现在来了解一下yield实现协程。

引用官方的说法:

  用yield实现python协程

与线程相比,协程更轻量。一个python线程大概占用8M内存,而一个协程只占用1KB不到内存。协程更适用于IO密集型的应用。

当然在讲协程的实现之前,有必要先来看一下send方法。

send方法

yield表达式有一个返回值,send方法的作用就是控制这个返回值,send的参数就是yield表达式的返回值。我们来看一下官方文档上关于send的定义:

用yield实现python协程

举个栗子:

用yield实现python协程

上面的代码输出:

用yield实现python协程

第一次调用next的时候,程序从函数最开始处运行,打印出

before yield

执行到yield处,停在该处。

接下来,向生成器send(1) 。send在这里起到两个作用,一个是将参数赋给yield的返回值,然后该返回值赋给了变量x;一个是继续程序的执行,直到下一次遇到yield停下来,第二个功能和next相似。其实,next就相当于send(None)。

之心了send(1)后,x被赋值给yield的返回值,即send的参数1,并继续往下执行,打印出了

after yield:1

继续执行,回到循环的开始,向下执行,打印出

before yield

再次遇到yield,停在该处,等待下一次send 或者next的调用。

向生成器send(2)。这里的步骤和send(1)相同,打印出下面两条后,在yield处停住。

after yield:2

before yield

执行next(g),x被赋值为yield表达式的返回值,也就是None,继续向下执行,打印出

after yield:None

再次回到循环的开始,向下执行,打印出

before yield

程序运行结束

现在是不是有点理解send了?

yield和send实现python协程

我们用协程实现一个生产者、消费者的例子:

用yield实现python协程

运行上面的程序,会输出:

用yield实现python协程

produce函数负责生产数据,consume函数负责消费数据。具体执行过程如下:

1  首先调用consume函数。consume函数的返回是一个生成器,把这个生成器传入produce函数。

2  produce函数中调用next(c)启动生成器。

3  计算n = n + 1生成数据,一旦生产了数据,调用c.send(n) 切换到consume执行。

4  consume函数中拿到数据后赋值给n,继续执行yield后面的语句

5  consume函数中打印消费的数据,并设置返回值r,又回到循环的开始,通过yield把结果传回。

6  produce拿到consume返回的值,继续生产下一个数据。

7  5个数据生产完毕后,循环结束,通过c.close() 关闭consume,结束全过程

produce和consume函数在一个线程内执行,通过调用send方法和yield互相切换,实现协程的功能