摘要:協程的歷史說來話長,要從生成器開始講起。我們可以使用把數據發送給協程函數。可以看到,在第次接收完數據之后,會產生結束的異常,因為程序流程結束了,這是正常現象。在這個階段,協程本質上還是由生成器構成的。所以,協程的介紹到這里就結束啦。
在上一篇對python并發編程的理解 中,我簡單提到了協程的概念,有一個錯誤需要指出的是,asyncio不全是對協程的實現,只是用到了協程。
協程的歷史說來話長,要從生成器開始講起。
如果你看過我之前的文章python奇遇記:迭代器和生成器 ,對生成器的概念應該很了解。生成器節省內存,用的時候才生成結果。
# 生成器表達式 a = (x*x for x in range(10)) # next生成值 next(a()) # 輸出0 next(a()) # 輸出1 next(a()) # 輸出4
與生成器產出數據不同的是,協程在產出數據的同時還可以接收數據,具體來說就是把yield 放在了表達式的右邊。我們可以使用.send() 把數據發送給協程函數。
def writer(): print("-> coroutine started") for i in range(8): w = yield print(i+w) w = writer() # 本質還是生成器 >>> w# 首先要用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,之后再傳遞到writer 。
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 ,新加入了兩個關鍵字async 和await ,同時協程不再是生成器類型,而是原生的協程類型。
現在我們定義一個協程要像下面這樣:
async def func(): await "some code"
不用于異步的協程該怎么用,我還不知道。所以,協程的介紹到這里就結束啦。
本人才疏學淺,上文中難免有些錯誤,還請各位品評指正。如果覺得寫的還行,歡迎關注我的公眾號MLGroup,講解python和機器學習方面的知識。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41264.html
摘要:反對的意見主要是這樣可能會破壞掉無數個腳本,而且中已經有太多的魔法了。除此之外,的命名本身也算是一種包袱。首字母大寫的,譯作史努比,則是一只被很多人喜愛的漫畫小狗。 showImg(https://segmentfault.com/img/remote/1460000019559250); 本文原創并首發于公眾號【Python貓】,未經授權,請勿轉載。 原文地址:https://mp....
摘要:所以與多線程相比,線程的數量越多,協程性能的優勢越明顯。值得一提的是,在此過程中,只有一個線程在執行,因此這與多線程的概念是不一樣的。 真正有知識的人的成長過程,就像麥穗的成長過程:麥穗空的時候,麥子長得很快,麥穗驕傲地高高昂起,但是,麥穗成熟飽滿時,它們開始謙虛,垂下麥芒。 ——蒙田《蒙田隨筆全集》 上篇論述了關于python多線程是否是雞肋的問題,得到了一些網友的認可,當然也有...
摘要:進程線程和協程進程的定義進程,是計算機中已運行程序的實體。協程和線程的關系協程是在語言層面實現對線程的調度,避免了內核級別的上下文消耗。和都引入了消息調度系統模型,來避免鎖的影響和進程線程開銷大的問題。 進程、線程和協程 進程的定義: 進程,是計算機中已運行程序的實體。程序本身只是指令、數據及其組織形式的描述,進程才是程序的真正運行實例。 線程的定義: 操作系統能夠進行運算調度的最小單...
摘要:項目地址我之前翻譯了協程原理這篇文章之后嘗試用了模式下的協程進行異步開發,確實感受到協程所帶來的好處至少是語法上的。 項目地址:https://git.io/pytips 我之前翻譯了Python 3.5 協程原理這篇文章之后嘗試用了 Tornado + Motor 模式下的協程進行異步開發,確實感受到協程所帶來的好處(至少是語法上的:D)。至于協程的 async/await 語法是如...
閱讀 713·2023-04-25 17:54
閱讀 2971·2021-11-18 10:02
閱讀 1132·2021-09-28 09:35
閱讀 649·2021-09-22 15:18
閱讀 2847·2021-09-03 10:49
閱讀 3051·2021-08-10 09:42
閱讀 2572·2019-08-29 16:24
閱讀 1254·2019-08-29 15:08