python協程的前世此生

在上一篇對python併發編程的理解 中,我簡單提到了協程的概念,有一個錯誤須要指出的是,asyncio不全是對協程的實現,只是用到了協程。python

協程的歷史說來話長,要從生成器開始講起。編程

若是你看過我以前的文章python奇遇記:迭代器和生成器 ,對生成器的概念應該很瞭解。生成器節省內存,用的時候才生成結果。併發

# 生成器表達式
a = (x*x for x in range(10))

# next生成值
next(a()) # 輸出0
next(a()) # 輸出1
next(a()) # 輸出4

與生成器產出數據不一樣的是,協程在產出數據的同時還能夠接收數據,具體來講就是把yield 放在了表達式的右邊。咱們可使用.send() 把數據發送給協程函數。app

def writer():
    print('-> coroutine started')
    for i in range(8):
        w = yield
        print(i+w)

w = writer()
# 本質仍是生成器
>>> w
<generator object writer at 0x000002595BC57468>
# 首先要用next()把協程激活
>>> next(w)
-> coroutine started
# 發送數據
>>> w.send(1)
1
# send到第八次以後會拋出異常
# 由於協程已經結束了
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)

第一步必須使用next() 激活協程函數,這樣才能在下一步使用.send() 發送數據。機器學習

能夠看到,在第8次接收完數據以後,會產生結束的異常,由於程序流程結束了,這是正常現象。加個異常處理便可。若是須要在兩個協程間傳遞數據呢?異步

def writer():
    while True:
        w = yield
        print('>>', w)

def writer_wrapper(coro):
    # 激活
    next(coro)
    while True:
        # 異常處理
        try:
            x = yield
            # 發送數據給writer
            coro.send(x)
        except StopIteration:
            pass
w = writer()
wrap = writer_wrapper(w)
# 激活
next(wrap)
for i in range(4):
    wrap.send(i)
# 輸出
>> 0
>> 1
>> 2
>> 3

上面的代碼中,數據首先傳遞到writer_wrapper,以後再傳遞到writerasync

data——>writer_wrapper——>writer異步編程

能夠這麼寫,不過,又要預先激活,又要加異常,看起來有點麻煩啊。yield from 的出現能夠解決這個問題,一樣是傳遞數據:函數

def writer():
    while True:
        w = yield
        print('>>', w)
        
def writer_wrapper2(coro):
    yield from coro

一行代碼解決問題。學習

總之,yield from至關於提供了一個通道,使得數據能夠在協程之間流轉writer_wrapper2 中使用yield from coro時,coro此時得到控制權,在咱們.send() 數據時,writer_wrapper2 被阻塞,直到writer 打印出結果。

在這個階段,協程本質上仍是由生成器構成的。

but,

即便咱們使用yield from 簡化了流程,協程和生成器的知識理解起來仍是有點懵逼,並且yield from 用在異步編程中有諸多不順(asyncio之前就是用yield from),因而在3.5版本的python中,棄用了yield from ,新加入了兩個關鍵字asyncawait ,同時協程再也不是生成器類型,而是原生的協程類型。

如今咱們定義一個協程要像下面這樣:

async def func():
    await 'some code'

不用於異步的協程該怎麼用,我還不知道。因此,協程的介紹到這裏就結束啦。


本人才疏學淺,上文中不免有些錯誤,還請各位品評指正。若是以爲寫的還行,歡迎關注個人公衆號MLGroup,講解python和機器學習方面的知識。
圖片描述

相關文章
相關標籤/搜索