python 协程(coroutine)工作原理

2018-07-16 207次浏览 发表评论

先了解一下Python 生成器的send()方法:

send()是python生成器的一个方法,send()方法有一个参数,该参数指定的是上一次被挂起的yield语句的返回值。看一个例子:

def gen():
    r = ''
    while True:
        """
        可以把n = yield r理解为一个接收机,可以接受外部通过send()传进来的值。
        每次运行到这里,会先执行yield r返回r,再把返回值赋给n。
        """
        n = yield r   #这里不管有没有n接收传入值,yield总是send传入的东西
        print(n)
        r = 'OK'

g = gen()

#启动生成器
g.send(None)

#再次调用生成器并传入返回值,然后输出返回值,此时r已经赋值为OK
print(g.send('aaaaaaaaaa'))
g.close()

执行结果:

aaaaaaaaaa
OK

协程

协程(Coroutine)在执行过程中可中断去执行其他任务,执行完毕后再回来继续原先的操作。可以理解为两个或多个程序协同工作

协程特点在于单线程执行:

优势一:具有极高的执行效率,因为在任务切换的时候是程序之间的切换(由程序自身控制)而不是线程间的切换,所以没有线程切换导致的额外开销(时间浪费),线程越多,携程性能优势越明显。

优势二:由于是单线程工作,没有多线程需要考虑的同时写变量冲突,所以不需要多线程的锁机制,故执行效率比多线程更高。

常利用多进程(利用多核)+协程来获取更高的性能。

讲工作原理前先了解yield,它不仅可以返回一个值,还可以接收调用者发出的参数。

代码如下:

def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        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()

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

每次运行到r = c.send(n)的时候,先执行=右边部分:将n通过send()传入consumer()中,即n=send(n),继续往下执行到将200 ok赋给r再一次运行到n = yield r的时候,yield会返回r;接着又切换到了produce()函数,返回的r被赋给了r。这就是整个的运行过程。

原文学习地址-廖雪峰     其实学完对send方法的工作流程/原理还是一脸懵逼~~

评论

随便说点,聊聊天~