標籤:yield producing ret 線程 zhang 部落格 原來 數組 角度
在跟著廖雪峰的部落格學習python,看到產生器這一章節的時候,首先提到了generator 、yield,然後在搜尋資料的時候,又查到了協程這一概念,這篇文章總結一下這幾個概念.
generator 從字面上理解,就是產生器,它的實現方式有兩種:
1、不同於清單產生器([]),而是用 ()來表示。(原來這種叫做產生器運算式哦,哈哈)
訪問方式,可以用for 迴圈來訪問,也可以用 .next 來訪問。
N = [‘Hello‘, ‘World‘, 18, ‘Apple‘, ‘None‘]hh = (s.lower() for s in N if isinstance(s,str) ==True)print hh#for item in hh:# print item#print hh.next()#print hh.next()#print hh.next()#print hh.next()
輸出結果
<generator object <genexpr> at 0x7f543a074690>
hello
world
apple
none
hh 是產生器返回的值,類似於一個數組。支援 for逐一查看和 .next()訪問,有一點需要注意的是,for 迴圈執行完了之後就不能執行 hh.next()了,類似於指標到了最後,或者C++中迭代器指向了最後,再訪問就會出現錯誤。
2、用yield來產生 ,(叫做產生器函數)
無論用next() 和for 迴圈來調用,都是執行到了yield之後,返回 n值,然後將當前的狀態掛起,然後返回。
def create_counter(n): print "create counter" #while True: while False: yield n print ‘increment n‘ n += 1cnt = create_counter(2)#print cntfor item in cnt: print item#print next(cnt)#print next(cnt)#print cnt.next()#print cnt.next()
比如這個例子中,當列印cnt的時候,<generator object create_counter at 0x7fa992b8d6e0>
說明這是一個,產生器。
當 為False的時候,只會列印 create counter
當為True的時候,用for 迴圈就會出現死迴圈的情況。
協程:
我知道有進程、線程的概念,但是協程是什麼東西,我還真是不知道
從技術的角度來說,“協程就是你可以暫停執行的函數”。如果你把它理解成“就像產生器一樣”,那麼你就想對了。這是在一篇文章上看到的。
python之所以執行效率高
1、為子程式切換不是線程切換,而是由程式自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的效能優勢就越明顯。
2、執行的過程中不會涉及到鎖機制。
附一個簡單的生產者和消費者的例子:
def consumer(): r = ‘‘ while True: n = yield r if not n: return print(‘[CONSUMER] Consuming %s...‘ % n) time.sleep(1) r = ‘200 OK‘def produce(c): c.next() 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()if __name__==‘__main__‘: c = consumer() produce(c)
1. consumer函數是一個generator。
2. c.send(None)其實等價於next(c),第一次執行時其實只執行到n = yield r就停止了,然後把r的值返回給調用者。
3. yield r是一個運算式,通過send(msg)被賦值,而send(msg)是有傳回值的,傳回值為:下一個yield r運算式的參數,即為r。
4. produce一旦生產了東西,通過c.send(n)切換到consumer執行。consumer通過yield拿到訊息,處理,又通過yield把結果傳回。也就是說,c.send(1) 不但會給 c 傳送一個資料,它還會等著下次 yield 從 c 中返回一個資料,它是有傳回值的,一去一回才算完,拿到了返回的資料(200 OK)才繼續下面執行。
5. 整個流程無鎖,由一個線程執行,produce和consumer協作完成任務,所以稱為“協程”,而非線程的搶佔式多任務。
總結來說,就是 yield r 是一個運算式,通過 c.send 被賦值,然後傳回值為下一個為yield r 運算式的參數。
github路徑:https://github.com/billzhangjingle/learnPython/basic/generator.py
在學習的時候搜尋到的相關部落格:
http://python.jobbole.com/86069/
http://python.jobbole.com/86481/
http://www.cnblogs.com/gide/p/6187080.html
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000
http://www.cnblogs.com/cotyb/p/5260032.html
python之產生器-generator