本文共 2154 字,大约阅读时间需要 7 分钟。
既然要说到协程,就不得不先提一下 yield 的用法了,yield 最主要的用法就两种。yield r 和 n = yield r ,
yield 简要理解:yield 就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。
def foo(): print("starting...") while True: res = yield 4 print("res:", res)g = foo()print(next(g))print("-" * 20)print(next(g))
starting...4--------------------res: None4
n = yield r 和 r = c.send(n)
def foo(): print("starting...") while True: res = yield 4 print("res:", res)g = foo()print(next(g))print("-" * 20)# print(next(g))print(g.send(7))
starting...4--------------------res: 74
通过上面的例子不难理解,next(g) 和 g.send(param) 其实是比较类似的,只不过后面这个在进行下一步的时候传递了参数进去,或者你也可以认为 next(g) 也传递了参数进去,只不过传递的是 None 而已。
所以,这也可以解释为什么 next(g) 也可以用 g.send(None) 来替换。
如果还有疑问的话,可以看看这篇博客:,相信这篇博客看了之后,你再看下面例子的代码就不那么费劲了 。
协程最大的优势就是极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
一般讲协程的时候喜欢用下面这个经典的生产者消费者的例子:
import timedef consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] Consuming %s...' % n) time.sleep(1) r = '200 OK'def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close()if __name__ == '__main__': c = consumer() produce(c)
执行结果:
[PRODUCER] Producing 1...[CONSUMER] Consuming 1...[PRODUCER] Consumer return: 200 OK[PRODUCER] Producing 2...[CONSUMER] Consuming 2...[PRODUCER] Consumer return: 200 OK[PRODUCER] Producing 3...[CONSUMER] Consuming 3...[PRODUCER] Consumer return: 200 OK[PRODUCER] Producing 4...[CONSUMER] Consuming 4...[PRODUCER] Consumer return: 200 OK[PRODUCER] Producing 5...[CONSUMER] Consuming 5...[PRODUCER] Consumer return: 200 OK
运行流程:
注意到consumer
函数是一个generator
,把一个consumer
传入produce
后:
首先调用c.send(None)
启动生成器 (其实用 next(c) 启动也是可以的);
然后,一旦生产了东西,通过c.send(n)
切换到consumer
执行;
consumer
通过yield
拿到消息,处理,又通过yield
把结果传回;
produce
拿到consumer
处理的结果,继续生产下一条消息;
produce
决定不生产了,通过c.close()
关闭consumer
,整个过程结束。
整个流程无锁,由一个线程执行,produce
和consumer
协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
转载地址:http://aijqi.baihongyu.com/