淺析python協(xié)程相關(guān)概念
這篇文章是讀者朋友的python協(xié)程的學習經(jīng)驗之談,以下是全部內(nèi)容:
協(xié)程的歷史說來話長,要從生成器開始講起。
如果你看過我之前的文章python奇遇記:迭代器和生成器 ,對生成器的概念應該很了解。生成器節(jié)省內(nèi)存,用的時候才生成結(jié)果。
# 生成器表達式 a = (x*x for x in range(10)) # next生成值 next(a()) # 輸出0 next(a()) # 輸出1 next(a()) # 輸出4
與生成器產(chǎn)出數(shù)據(jù)不同的是,協(xié)程在產(chǎn)出數(shù)據(jù)的同時還可以接收數(shù)據(jù),具體來說就是把yield 放在了表達式的右邊。我們可以使用.send() 把數(shù)據(jù)發(fā)送給協(xié)程函數(shù)。
def writer(): print('-> coroutine started') for i in range(8): w = yield print(i+w) w = writer() # 本質(zhì)還是生成器 >>> w <generator object writer at 0x000002595BC57468> # 首先要用next()把協(xié)程激活 >>> next(w) -> coroutine started # 發(fā)送數(shù)據(jù) >>> w.send(1) 1 # send到第八次之后會拋出異常 # 因為協(xié)程已經(jīng)結(jié)束了 --------------------------------------------------------------------------- StopIteration Traceback (most recent call last)
第一步必須使用next() 激活協(xié)程函數(shù),這樣才能在下一步使用.send() 發(fā)送數(shù)據(jù)。
可以看到,在第8次接收完數(shù)據(jù)之后,會產(chǎn)生結(jié)束的異常,因為程序流程結(jié)束了,這是正常現(xiàn)象。加個異常處理即可。如果需要在兩個協(xié)程間傳遞數(shù)據(jù)呢?
def writer(): while True: w = yield print('>>', w) def writer_wrapper(coro): # 激活 next(coro) while True: # 異常處理 try: x = yield # 發(fā)送數(shù)據(jù)給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
上面的代碼中,數(shù)據(jù)首先傳遞到writer_wrapper,之后再傳遞到writer 。
data——>writer_wrapper——>writer
可以這么寫,不過,又要預先激活,又要加異常,看起來有點麻煩啊。yield from 的出現(xiàn)可以解決這個問題,同樣是傳遞數(shù)據(jù):
def writer(): while True: w = yield print('>>', w) def writer_wrapper2(coro): yield from coro
一行代碼解決問題。
總之,yield from相當于提供了一個通道,使得數(shù)據(jù)可以在協(xié)程之間流轉(zhuǎn) 。writer_wrapper2 中使用yield from coro時,coro此時獲得控制權(quán),在我們.send() 數(shù)據(jù)時,writer_wrapper2 被阻塞,直到writer 打印出結(jié)果。
在這個階段,協(xié)程本質(zhì)上還是由生成器構(gòu)成的。
即使我們使用yield from 簡化了流程,協(xié)程和生成器的知識理解起來還是有點懵逼,而且yield from 用在異步編程中有諸多不順(asyncio以前就是用yield from),于是在3.5版本的python中,棄用了yield from ,新加入了兩個關(guān)鍵字async 和await ,同時協(xié)程不再是生成器類型,而是原生的協(xié)程類型。
現(xiàn)在我們定義一個協(xié)程要像下面這樣:
async def func(): await 'some code'
不用于異步的協(xié)程該怎么用,我還不知道。所以,協(xié)程的介紹到這里就結(jié)束啦。感謝你對腳本之家的支持。
相關(guān)文章
pytorch無坑安裝CPU版小白教程(配gpu版鏈接、conda命令教程)
pip安裝無論是cpu還是gpu的pytorch安裝,其實官方給了很好的安裝流程,本文主要介紹了pytorch無坑安裝CPU版小白教程,具有一定的參考價值,感興趣的可以了解一下2024-03-03python數(shù)據(jù)分析工具之 matplotlib詳解
對于 Python 來說,matplotlib 是最著名的繪圖庫,它主要用于二維繪圖,當然也可以進行簡單的三維繪圖。這篇文章主要介紹了python數(shù)據(jù)分析工具之 matplotlib的相關(guān)知識,需要的朋友可以參考下2020-04-04