在跟著廖雪峰的博客學習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()
輸出結果
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 nprint '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的時候,
#說明這是一個,生成器。
當 為False的時候,只會印出 create counter
當為True的時候,用for 循環就會出現死循環的情況。
協程:
我知道有行程、執行緒的概念,但是協程是什麼東西,我還真是不知道
從技術的角度來說,「協程就是你可以暫停執行的函數」。如果你把它理解成“就像生成器一樣”,那麼你就想對了。這是在一篇文章上看到的。
python之所以執行效率高
1、為子程式切換不是執行緒切換,而是由程式本身控制,因此,沒有執行緒切換的開銷,和多執行緒比,線程數量越多,協程的效能優勢就越明顯。
2、執行的過程中不會涉及到鎖定機制。
附上一個簡單的生產者與消費者的例子:
def consumer(): r = ''while True: n = yield rif not n:returnprint('[CONSUMER] Consuming %s...' % n) time.sleep(1) r = '200 OK'def produce(c): c.next() n = 0while n < 5: n = n + 1print('[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 表達式的參數。
以上是python生成器generator介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!