1、yield放在函数中可以使得函数变成生成器,也可以变成协程。
2、用yielld构造的生成器可以作为协程使用,协程是指一个过程,这个过程与调用方协作,由调用方提供的值,来计算并产出。
3、纯粹的生成器只输出值,和迭代有关,这样可以交接给for调用。
4、协程与函数的区别,函数是一种上下级调用关系,而协程是通过yield方式转移执行权,对称而平级的调用对方,典型的有生产者和消费者。
协程实现的伪代码如下:
# producer coroutine
loop
while queue is not full
create some new items
add the items to queue
yield to consumer
# consumer coroutine
loop
while queue is not empty
remove some items from queue
use the items
yield to producer
上述伪代码用python实现后,可得出如下:
# -*- coding:utf-8 -*-
import queue
import random
limit = 9
q = queue.Queue()
def producer():
while True:
cap = limit - q.qsize()
while cap > 0:
q.put(random.randint(0, 100))
cap -= 1
print('producer 通过yield将控制权让出')
yield 'consumer'
def consumer():
while True:
cap = q.qsize()
while cap > 0:
item = q.get()
print(item)
cap -= 1
print('consumer 通过yield将控制权让出')
yield 'producer'
dic = {
'producer': producer(),
'consumer': consumer()
}
current = dic['producer']
times = 8
while times > 0:
current = dic[next(current)]
times -= 1
目前为止,我们只讲清楚了,协程的概念,但是这样还不能解决阻塞和并发问题。
解决阻塞的方式就并发,从用户的角度来说,我并没有停下来等待,也就是并发。
比如,从消费者来说,没有感觉生产者在生产,从生产者来说,没有感觉消费者在消费,要实现上述效果,就要缩短在生产者和消费者的执行时间,给人的感觉时消费和生产同时进行,互不干扰。
# -*- coding:utf-8 -*-
import queue
import random
import time
limit = 1
q = queue.Queue()
def producer():
while True:
cap = limit - q.qsize()
print('开始生产')
while cap > 0:
time.sleep(.1)
q.put(random.randint(0, 100))
cap -= 1
#print('生产OK 通过yield将控制权让出')
yield 'consumer'
def consumer():
while True:
cap = q.qsize()
print('开始消费')
while cap > 0:
time.sleep(.1)
item = q.get()
#print(item)
cap -= 1
#print('consumer 通过yield将控制权让出')
yield 'producer'
dic = {
'producer': producer(),
'consumer': consumer()
}
current = dic['producer']
times = 8
while times > 0:
current = dic[next(current)]
times -= 1