精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python增強的生成器:協(xié)程

開發(fā) 后端
本文主要介紹python中Enhanced generator即coroutine相關(guān)內(nèi)容,包括基本語法、使用場景、注意事項,以及與其他語言協(xié)程實現(xiàn)的異同。

[[202482]]

本文主要介紹python中Enhanced generator即coroutine相關(guān)內(nèi)容,包括基本語法、使用場景、注意事項,以及與其他語言協(xié)程實現(xiàn)的異同。

enhanced generator

在上文《Python Yield Generator 詳解》中介紹了yield和generator的使用場景和主意事項,只用到了generator的next方法,事實上generator還有更強大的功能。PEP 342為generator增加了一系列方法來使得generator更像一個協(xié)程Coroutine。做主要的變化在于早期的yield只能返回值(作為數(shù)據(jù)的產(chǎn)生者), 而新增加的send方法能在generator恢復(fù)的時候消費一個數(shù)值,而去caller(generator的調(diào)用著)也可以通過throw在generator掛起的主動拋出異常。

  1. back_data = yield cur_ret 

這段代碼的意思是:當執(zhí)行到這條語句時,返回cur_ret給調(diào)用者;并且當generator通過next()或者send(some_data)方法恢復(fù)的時候,將some_data賦值給back_data.例如:

  1. def gen(data): 
  2.  
  3.     print 'before yield', data 
  4.  
  5.     back_data = yield data 
  6.  
  7.     print 'after resume', back_data 
  8.  
  9.      
  10.  
  11. if __name__ == '__main__'
  12.  
  13.     g = gen(1) 
  14.  
  15.     print g.next() 
  16.  
  17.     try: 
  18.  
  19.         g.send(0) 
  20.  
  21.     except StopIteration: 
  22.  
  23.         pass  

輸出:

  1. before yield 1 
  2.  
  3.  
  4. after resume 0  

兩點需要注意:

  1. next() 等價于 send(None)
  2. ***次調(diào)用時,需要使用next()語句或是send(None),不能使用send發(fā)送一個非None的值,否則會出錯的,因為沒有Python yield語句來接收這個值。

應(yīng)用場景

當generator可以接受數(shù)據(jù)(在從掛起狀態(tài)恢復(fù)的時候) 而不僅僅是返回數(shù)據(jù)時, generator就有了消費數(shù)據(jù)(push)的能力。下面的例子來自這里:

  1. word_map = {} 
  2.  
  3. def consume_data_from_file(file_name, consumer): 
  4.  
  5.     for line in file(file_name): 
  6.  
  7.         consumer.send(line)      
  8.  
  9. def consume_words(consumer): 
  10.  
  11.     while True
  12.  
  13.         line = yield 
  14.  
  15.         for word in (w for w in line.split() if w.strip()): 
  16.  
  17.             consumer.send(word)      
  18.  
  19. def count_words_consumer(): 
  20.  
  21.     while True
  22.  
  23.         word  = yield 
  24.  
  25.         if word not in word_map: 
  26.  
  27.             word_map[word] = 0 
  28.  
  29.         word_map[word] += 1 
  30.  
  31.     print word_map      
  32.  
  33. if __name__ == '__main__'
  34.  
  35.     cons = count_words_consumer() 
  36.  
  37.     cons.next() 
  38.  
  39.     cons_inner = consume_words(cons) 
  40.  
  41.     cons_inner.next() 
  42.  
  43.     c = consume_data_from_file('test.txt', cons_inner) 
  44.  
  45.     print word_map  

上面的代碼中,真正的數(shù)據(jù)消費者是count_words_consumer,最原始的數(shù)據(jù)生產(chǎn)者是consume_data_from_file,數(shù)據(jù)的流向是主動從生產(chǎn)者推向消費者。不過上面第22、24行分別調(diào)用了兩次next,這個可以使用一個decorator封裝一下。

  1. def consumer(func): 
  2.  
  3.     def wrapper(*args,**kw): 
  4.  
  5.         gen = func(*args, **kw) 
  6.  
  7.         gen.next() 
  8.  
  9.         return gen 
  10.  
  11.     wrapper.__name__ = func.__name__ 
  12.  
  13.     wrapper.__dict__ = func.__dict__ 
  14.  
  15.     wrapper.__doc__  = func.__doc__ 
  16.  
  17.     return wrapper  

修改后的代碼:

  1. def consumer(func): 
  2.  
  3.     def wrapper(*args,**kw): 
  4.  
  5.         gen = func(*args, **kw) 
  6.  
  7.         gen.next() 
  8.  
  9.         return gen 
  10.  
  11.     wrapper.__name__ = func.__name__ 
  12.  
  13.     wrapper.__dict__ = func.__dict__ 
  14.  
  15.     wrapper.__doc__  = func.__doc__ 
  16.  
  17.     return wrapper      
  18.  
  19. word_map = {} 
  20.  
  21. def consume_data_from_file(file_name, consumer): 
  22.  
  23.     for line in file(file_name): 
  24.  
  25.         consumer.send(line)      
  26.  
  27. @consumer 
  28.  
  29. def consume_words(consumer): 
  30.  
  31.     while True
  32.  
  33.         line = yield 
  34.  
  35.         for word in (w for w in line.split() if w.strip()): 
  36.  
  37.             consumer.send(word)      
  38.  
  39. @consumer 
  40.  
  41. def count_words_consumer(): 
  42.  
  43.     while True
  44.  
  45.         word  = yield 
  46.  
  47.         if word not in word_map: 
  48.  
  49.             word_map[word] = 0 
  50.  
  51.         word_map[word] += 1 
  52.  
  53.     print word_map      
  54.  
  55. if __name__ == '__main__'
  56.  
  57.     cons = count_words_consumer() 
  58.  
  59.     cons_inner = consume_words(cons) 
  60.  
  61.     c = consume_data_from_file('test.txt', cons_inner) 
  62.  
  63.     print word_map      
  64.  
  65. example_with_deco  

generator throw

除了next和send方法,generator還提供了兩個實用的方法,throw和close,這兩個方法加強了caller對generator的控制。send方法可以傳遞一個值給generator,throw方法在generator掛起的地方拋出異常,close方法讓generator正常結(jié)束(之后就不能再調(diào)用next send了)。下面詳細介紹一下throw方法。

  1. throw(type[, value[, traceback]]) 

在generator yield的地方拋出type類型的異常,并且返回下一個被yield的值。如果type類型的異常沒有被捕獲,那么會被傳給caller。另外,如果generator不能yield新的值,那么向caller拋出StopIteration異常:

  1. @consumer 
  2.  
  3. def gen_throw(): 
  4.  
  5.     value = yield 
  6.  
  7.     try: 
  8.         yield value 
  9.  
  10.     except Exception, e: 
  11.  
  12.         yield str(e) # 如果注釋掉這行,那么會拋出StopIteration      
  13.  
  14. if __name__ == '__main__'
  15.  
  16.     g = gen_throw() 
  17.  
  18.     assert g.send(5) == 5 
  19.  
  20.     assert g.throw(Exception, 'throw Exception') == 'throw Exception'  

***次調(diào)用send,代碼返回value(5)之后在第5行掛起, 然后generator throw之后會被第6行catch住。如果第7行沒有重新yield,那么會重新拋出StopIteration異常。

注意事項

如果一個生成器已經(jīng)通過send開始執(zhí)行,那么在其再次yield之前,是不能從其他生成器再次調(diào)度到該生成器

  1. @consumer 
  2.  
  3. def funcA(): 
  4.  
  5.     while True
  6.  
  7.         data = yield 
  8.  
  9.         print 'funcA recevie', data 
  10.  
  11.         fb.send(data * 2)      
  12.  
  13. @consumer 
  14.  
  15. def funcB(): 
  16.  
  17.     while True
  18.  
  19.         data = yield 
  20.  
  21.         print 'funcB recevie', data 
  22.  
  23.         fa.send(data * 2)      
  24.  
  25. fa = funcA() 
  26.  
  27. fb = funcB() 
  28.  
  29. if __name__ == '__main__'
  30.  
  31.     fa.send(10)  

輸出:

  1. funcA recevie 10 
  2.  
  3. funcB recevie 20 
  4.  
  5. ValueError: generator already executing  

Generator 與 Coroutine

回到Coroutine,可參見維基百科解釋,而我自己的理解比較簡單(或者片面):程序員可控制的并發(fā)流程,不管是進程還是線程,其切換都是操作系統(tǒng)在調(diào)度,而對于協(xié)程,程序員可以控制什么時候切換出去,什么時候切換回來。協(xié)程比進程 線程輕量級很多,較少了上下文切換的開銷。另外,由于是程序員控制調(diào)度,一定程度上也能避免一個任務(wù)被中途中斷.。協(xié)程可以用在哪些場景呢,我覺得可以歸納為非阻塞等待的場景,如游戲編程,異步IO,事件驅(qū)動。

Python中,generator的send和throw方法使得generator很像一個協(xié)程(coroutine), 但是generator只是一個半?yún)f(xié)程(semicoroutines),python doc是這樣描述的:

“All of this makes generator functions quite similar to coroutines; they yield multiple times, they have more than one entry point and their execution can be suspended. The only difference is that a generator function cannot control where should the execution continue after it yields; the control is always transferred to the generator’s caller.”

盡管如此,利用enhanced generator也能實現(xiàn)更強大的功能。比如上文中提到的yield_dec的例子,只能被動的等待時間到達之后繼續(xù)執(zhí)行。在某些情況下比如觸發(fā)了某個事件,我們希望立即恢復(fù)執(zhí)行流程,而且我們也關(guān)心具體是什么事件,這個時候就需要在generator send了。另外一種情形,我們需要終止這個執(zhí)行流程,那么刻意調(diào)用close,同時在代碼里面做一些處理,偽代碼如下:

  1. @yield_dec 
  2.  
  3. def do(a): 
  4.  
  5.     print 'do', a 
  6.  
  7.     try: 
  8.  
  9.         event = yield 5 
  10.  
  11.         print 'post_do', a, event 
  12.  
  13.     finally: 
  14.  
  15.         print 'do sth'  

至于之前提到的另一個例子,服務(wù)(進程)之間的異步調(diào)用,也是非常適合實用協(xié)程的例子。callback的方式會割裂代碼,把一段邏輯分散到多個函數(shù),協(xié)程的方式會好很多,至少對于代碼閱讀而言。其他語言,比如C#、Go語言,協(xié)程都是標準實現(xiàn),特別對于go語言,協(xié)程是高并發(fā)的基石。在python3.x中,通過asyncio和async\await也增加了對協(xié)程的支持。在筆者所使用的2.7環(huán)境下,也可以使用greenlet,之后會有博文介紹。

參考

  • https://www.python.org/dev/peps/pep-0342/
  • http://www.dabeaz.com/coroutines/
  • https://en.wikipedia.org/wiki/Coroutine#Implementations_for_Python 
責任編輯:龐桂玉 來源: Python開發(fā)者
相關(guān)推薦

2021-09-16 09:59:13

PythonJavaScript代碼

2021-12-04 22:07:44

Python

2023-08-25 09:51:21

前端開發(fā)

2024-02-05 09:06:25

Python協(xié)程Asyncio庫

2010-09-07 16:31:17

SQL語句insert

2011-12-23 13:42:05

JavaScript

2021-04-22 21:15:38

Generator函數(shù)生成器

2017-07-01 16:02:39

分布式ID生成器

2025-01-23 08:36:27

CSS開發(fā)工具

2015-08-25 11:07:58

2021-08-11 20:20:51

Python異步列表

2023-05-04 16:24:10

人工智能圖像生成器

2023-02-07 16:11:41

2022-10-17 18:29:55

2020-10-05 21:57:43

Python生成器可迭代對象

2022-07-25 10:27:36

背景生成器工具前端

2017-06-26 16:26:15

Python迭代對象迭代器

2021-12-09 06:41:56

Python協(xié)程多并發(fā)

2024-11-01 15:51:06

2021-06-06 16:31:57

PythonPython 3.7 編程語言
點贊
收藏

51CTO技術(shù)棧公眾號

av免费观看不卡| xxxxxx在线观看| 中文字幕1区2区3区| 91中文字幕精品永久在线| 日韩午夜在线观看视频| 2022亚洲天堂| 黄色网在线播放| www.色综合.com| 国产情人节一区| 国产成人无码精品久久久久| 欧美在线电影| 亚洲变态欧美另类捆绑| 99热手机在线| 丁香花高清在线观看完整版| 国产欧美一区二区在线观看| 51精品国产人成在线观看| 亚洲精品1区2区3区| 天天射成人网| 亚洲人午夜精品| 亚洲区 欧美区| 草莓视频成人appios| 亚洲国产成人av| 一区二区三区|亚洲午夜| 三级网站免费观看| 国产精品中文欧美| 国产精品爽黄69天堂a| 成人免费视频毛片| 欧美三级午夜理伦三级中文幕| 中文字幕日韩av| 99re久久精品国产| 欧美日韩黄网站| 欧美日韩在线一区二区| www.爱色av.com| 国产区美女在线| 亚洲人成人一区二区在线观看 | 欧美性猛交bbbbb精品| 91av精品| 日韩专区在线播放| 91精品国自产在线| 国产探花在线精品| 亚洲欧洲xxxx| 特级西西人体wwwww| 成人福利一区| 精品国产一区二区三区久久久蜜月| 自拍偷拍21p| 免费观看成人性生生活片 | 日韩午夜视频在线| 91福利国产成人精品照片| 波多野结衣乳巨码无在线| 黑人精品视频| 亚洲国产乱码最新视频 | 99re在线播放| 国产理论片在线观看| 美女精品一区二区| 国产裸体写真av一区二区| 糖心vlog精品一区二区| 丝袜a∨在线一区二区三区不卡| 4438全国成人免费| 日本三级一区二区| 亚洲一区欧美激情| 日韩免费av在线| 波多野结衣高清在线| 日韩国产欧美在线播放| 国产福利视频一区二区| 免费观看日批视频| 免费成人你懂的| 国产欧洲精品视频| 国产高潮流白浆喷水视频| 国精品**一区二区三区在线蜜桃 | 国产亚洲欧美精品久久久久久| 久久精品高清| 久久精品人人做人人爽| 超碰手机在线观看| 精品成人久久| 欧美一级在线亚洲天堂| 亚洲 国产 日韩 欧美| 奇米精品一区二区三区四区| 国产日韩在线播放| 99精品在线视频观看| 国产99久久久精品| 精品欧美一区二区久久久伦| 黄色在线小视频| 国产精品久久久久aaaa| 麻豆传媒网站在线观看| 高端美女服务在线视频播放| 精品成人av一区| 日韩一级免费在线观看| 性欧美video另类hd尤物| 日韩欧美www| 好吊日免费视频| 色乱码一区二区三区网站| 久久国产精品久久久久久久久久| 久久精品女人毛片国产| 久久一二三四| 91九色视频在线观看| 亚洲三级中文字幕| 国产精品国产三级国产普通话99| 男人添女荫道口女人有什么感觉| 中文字幕在线视频久| 欧美日韩dvd在线观看| 一级黄色免费视频| 少妇一区二区视频| 欧美成人免费在线视频| 一区二区三区福利视频| 激情文学综合插| 鲁片一区二区三区| 国产网站在线免费观看| 欧美性猛交xxxx黑人| 搡的我好爽在线观看免费视频| 精品国产一区二区三区不卡蜜臂| 国产午夜精品美女视频明星a级| 99热精品免费| 日本成人中文字幕| 国产一区二区三区色淫影院| 亚洲xxxxxx| 狠狠色狠狠色综合日日小说| 欧美日韩久久婷婷| 国产影视一区| 亚洲97在线观看| 国产精品国产一区二区三区四区| 91蜜桃传媒精品久久久一区二区| 无码毛片aaa在线| 日韩精品三区| 亚洲精品乱码久久久久久金桔影视| 美国黑人一级大黄| 国产亚洲激情| 国产精品日韩一区二区| 看黄网站在线| 欧美日韩免费一区二区三区视频| av直播在线观看| 狠狠综合久久| 99久久无色码| 伊人福利在线| 欧美一区二区三区四区五区| 免费黄在线观看| 亚洲欧美日本日韩| 国产伦精品一区二区三区照片91| 麻豆传媒在线免费| 欧美视频第二页| 国产肥白大熟妇bbbb视频| 亚洲最黄网站| 激情视频一区二区| 华人av在线| 亚洲成人av资源网| 久久久久成人网站| 国产精品一区二区三区网站| 懂色av粉嫩av蜜臀av| 欧美在线se| 日韩一级黄色av| 亚洲一区二区三区高清视频| 日本一区二区三区免费乱视频| 日本中文字幕片| 国产调教一区二区三区| 国产精品久久网| av播放在线| 欧美日韩国产a| 男人av资源站| 国产原创一区二区| 欧美日韩中文字幕在线播放| 日韩一区免费| 欧美激情性做爰免费视频| 不卡视频在线播放| 亚洲福利一区二区三区| 丰满人妻一区二区三区免费视频棣| 欧美精品九九| 国产综合色一区二区三区| 手机av在线| 永久555www成人免费| 国产一区二区三区在线观看| 亚洲免费在线看| 中文字幕一区二区三区人妻在线视频 | 亚洲熟妇一区二区三区| 天堂成人国产精品一区| 亚洲国产日韩美| 欧美一区一区| 国内精品视频一区| 欧美一区二区三区激情| 欧美性猛交xxxx免费看久久久| 亚洲色成人网站www永久四虎| 麻豆成人91精品二区三区| 桥本有菜av在线| 老汉色老汉首页av亚洲| 国产精品91视频| 综合久久2019| 日韩精品中文字幕在线播放| 中文在线字幕免费观| 尤物av一区二区| 四虎永久免费在线观看| 韩国精品在线观看 | 老妇喷水一区二区三区| 这里只有精品66| 国产精品白丝一区二区三区| 国产a∨精品一区二区三区不卡| 337p日本欧洲亚洲大胆鲁鲁| 日韩欧美高清在线| 69视频免费看| 亚洲线精品一区二区三区八戒| 国产美女免费网站| 国产精品一区二区久久不卡| 日韩一级免费在线观看| 狠狠入ady亚洲精品| 亚洲丰满在线| 国产精品久久久久久久久久白浆| 国产精品极品在线| av电影免费在线看| 精品久久久999| 无码国产精品高潮久久99| 欧美日韩成人激情| 欧美一级淫片免费视频黄| 亚洲一区二区三区中文字幕| 日韩精品电影一区二区三区| 成人精品一区二区三区中文字幕| 亚洲性图一区二区| 午夜亚洲一区| 久久av综合网| 小小影院久久| 视频一区二区三| 性人久久久久| 国产不卡一区二区在线观看| 日韩av黄色| 国产精品成人一区| 麻豆免费在线| 久久久久久久久爱| 爆操欧美美女| xxxxx成人.com| 久久国产精品高清一区二区三区| 精品久久久三级丝袜| 国产又黄又爽视频| 欧美日韩在线播放一区| 精品人妻无码一区二区性色| 亚洲第一狼人社区| 精品99久久久久成人网站免费| 一区二区中文视频| 性爱在线免费视频| 国产嫩草影院久久久久| 免费毛片视频网站| 久久人人爽爽爽人久久久| 中文字幕精品久久久| 国产成人自拍高清视频在线免费播放| 久久人人爽av| 美女任你摸久久| 亚州精品一二三区| 日韩成人免费看| 亚洲中文字幕久久精品无码喷水| 一本色道久久| 国模无码视频一区二区三区| 亚洲欧洲综合| 国产精品一区二区免费在线观看| 在线观看视频免费一区二区三区| 成人短视频在线观看免费| 欧美一区二区三区另类| 国产精品视频网站在线观看 | 国产日韩欧美精品在线观看| 欧美亚韩一区| 免费观看国产精品视频| 国产日韩精品视频一区二区三区| 五月丁香综合缴情六月小说| 国产欧美日本| 欧美日韩在线视频一区二区三区| 亚洲综合不卡| 国产精品入口免费软件| 精品一区二区在线免费观看| 福利片一区二区三区| 韩国成人在线视频| 亚洲熟女乱综合一区二区| 高清久久久久久| 久久久久成人精品无码中文字幕| 99视频有精品| 国产精品免费无码| 亚洲欧美乱综合| 国产午夜激情视频| 色综合久久天天| 在线观看中文字幕码| 欧美二区乱c少妇| 性网爆门事件集合av| 亚洲第一网中文字幕| 免费资源在线观看| 久久久999精品| а√天堂8资源在线| 国产成人一区二区三区电影| 视频欧美精品| 国产精品传媒毛片三区| 久草成人在线| 青青草视频国产| 国产精品亚洲综合色区韩国| 浓精h攵女乱爱av| 国产精品一区二区在线观看不卡| 久久一区二区电影| 国产精品高潮久久久久无| 国产一级一片免费播放放a| 日本精品视频一区二区三区| 国产aⅴ一区二区三区| 日韩电影免费在线观看中文字幕 | 国产日韩欧美精品电影三级在线| 很污很黄的网站| 亚洲午夜在线电影| 中文字幕丰满人伦在线| 精品福利在线导航| 午夜在线视频| 97成人精品区在线播放| 电影一区二区三区久久免费观看| 国产一区二区三区四区五区加勒比 | 老司机亚洲精品| 欧美日韩一区二区区别是什么 | 精品少妇一区二区三区| 国产福利在线看| 国产做受高潮69| 欧美亚洲福利| 欧美成熟毛茸茸复古| 欧美在线影院| 最新国产黄色网址| 久久精品一级爱片| 国产一级一级片| 欧美一区二区日韩| 中文字幕在线观看日本| 欧美一级片在线播放| 试看120秒一区二区三区| 亚洲国产精品综合| 亚久久调教视频| 艳妇乳肉豪妇荡乳xxx| 亚洲人一二三区| 一区二区三区在线免费观看视频 | 成人免费视频网址| 国产一区二区观看| 狠狠干 狠狠操| 成人永久免费视频| 四虎免费在线视频| 欧美日产在线观看| 69视频在线观看| 国产成人综合久久| 国产欧美久久一区二区三区| 欧美二区在线视频| 国产91精品一区二区麻豆网站| 91久久久久久久久久久久久久| 欧洲一区在线观看| 黄色软件在线| 国产97在线播放| 九九热爱视频精品视频| 男女午夜激情视频| 91日韩一区二区三区| 日产亚洲一区二区三区| 精品对白一区国产伦| sqte在线播放| 国产高清在线一区二区| 欧美三级视频| 国产情侣久久久久aⅴ免费| 亚洲香蕉伊在人在线观| 免费观看黄一级视频| 久久久久久午夜| 老司机aⅴ在线精品导航| 热99这里只有精品| 99久久国产免费看| 色av性av丰满av| 国产亚洲一区二区精品| 91超碰碰碰碰久久久久久综合| 青娱乐一区二区| 美女视频第一区二区三区免费观看网站| 免费一级黄色录像| 制服丝袜中文字幕一区| www.久久ai| 成人免费91在线看| 夜夜嗨一区二区| 69精品无码成人久久久久久| 欧美日韩在线播放一区| www在线观看播放免费视频日本| av资源站久久亚洲| 亚洲精品人人| 国产熟妇久久777777| 欧美日韩小视频| 宅男在线观看免费高清网站| 国产欧美日韩一区二区三区| 国产欧美综合一区二区三区| 性欧美精品中出| 欧美一区二区在线免费观看| 丰满诱人av在线播放| 欧美不卡在线一区二区三区| 美女视频黄频大全不卡视频在线播放| 手机在线免费看片| 亚洲国产毛片完整版| 国产精品字幕| 国产免费裸体视频| 久久综合丝袜日本网| 一道本无吗一区| 韩国日本不卡在线| 成人亚洲一区| 91九色蝌蚪porny| 欧美亚洲高清一区二区三区不卡| 国产欧美黑人| 蜜桃传媒一区二区| 国产在线精品一区二区三区不卡 | 一本色道久久综合亚洲精品按摩| 在线视频三区| 国产伦精品一区二区三区| 日韩电影一区二区三区| 天天综合天天做| 亚洲欧美制服第一页| 2020国产精品极品色在线观看| 青青在线视频免费| 亚洲一区二区在线免费看| 懂色一区二区三区|