yield实现一个协程

send方法

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

generate.send(value):

生成器的send(value)方法会将value值“发送”给生成器中的方法。value参数变成当前yield表达式的值。
send()方法会返回生成器生成的下一个yield值或者StopIteration异常(如果生成器没有生成下一个yield值就退出了)。
当通过调用send()启动生成器时,value值必须为None,因为当前还没有yield表达式可以接收参数。

是不是看晕了?我们来看一个例子

def func():
    while True:
        print("before yield")
        x = yield
        print("after yield:",x)

g = func()
next(g) # 程序运行到yield并停在该处,等待下一个next
g.send(1) # 给yield发送值1,这个值被赋值给了x,并且打印出来,然后继续下一次循环停在yield处
g.send(2) # 给yield发送值2,这个值被赋值给了x,并且打印出来,然后继续下一次循环停在yield处
next(g) # 没有给x赋值,执行print语句,打印出None,继续循环停在yield处

上面的代码输出

before yield
after yield: 1
before yield
after yield: 2
before yield
after yield: None
before yield

第一次调用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实现协程

def producer():
    for i in range(100): # 0 1 2 3 4 5 6 ....
        n = yield i
        print("结果:",n  )		
		
def consumer():
    # 初始化当前生成器函数
    g = producer()
    # send可以类比next,第一次调用时,必须发送None,send给yield发送数据(上一个yield)
    g.send(None)
    for i in range(10): # 0 1 2 3 ... 9
        res = g.send(i)
        print(res)
consumer()
posted @ 2020-08-13 17:38  左晓龙  阅读(92)  评论(0编辑  收藏  举报