對yield 的理解
阿新 • • 發佈:2017-06-02
cti iter 模型 數據返回 語法 下一個 但是 consumer for in
最近在學習Python的時候看到yield的相關語法,感覺很獨特,相比其他如C/C++的語法比較有意思,於是在看完資料相關章節做一個總結。
yield 是一個類似於 return的語法,但是對於return 而言,在其執行之後,意味著將數據返回給調用者,子程序結束,但是yield卻不一樣,它能夠繼續執行,直到下一個yield 轉交執行權,之後又可以進入繼續執行,周而復始,直到拋出異常。
for in range()是一個簡單有用的循環,之前的學習知道range()返回的是一個對象,有惰性求值的特點,下面是一個利用yield簡單模擬range()函數的特點
def xrange(m): n=m while(n): n-=1 yield n for i in xrange(5): print(i)
結果:
‘‘‘ 4 3 2 1 0 ‘‘‘
這種獨特語法現象的原因,從書中摘出相關資料如下:
當函數中使用yield產生一個值的時候,調用函數會返回一個generator對象,也就是一個生成器,此對象有__next__()方法,通常會調用next()調用該方法取出下一個產生的值,若無法產生下一個值,就會發生StopIteration這樣的異常 --《Python程序設計教程》
除了解釋以上現象,反之也可推測 for in 函數的參數可以是生成器,生成器具有惰性求值特點,推測之前遇到過惰性求值的都是生成器(推測)
yield可以通過send函數來產生值,下面用一個課本上的DEMO來熟悉其相關函數的使用,課本完成了一個生產者消費者模型:
import random def producer(): while True: data=random.randint(0,9) print(‘生產了:‘,data) yield data def consumer(): while True: data=yield print(‘消費了:‘,data) def clerk(jobs,producer,consumer):print(‘執行了{}次生產與消費‘.format(jobs)) p=producer() c=consumer() next(c) #這裏容易出錯 for i in range(jobs): data=next(p) c.send(data) clerk(5,producer,consumer)
上面註釋的地方比較有意思,只是執行一次yield,而沒有任何輸出,似乎是沒用,但是刪除之後程序卻無法執行,我的理解是必須執行一次使值轉化成生成器對象才能接受相關數據。
為了印證我的觀點,執行以下代碼:
print(type(producer)) print(type(producer()))
輸出:
‘‘‘ <class ‘function‘> <class ‘generator‘> ‘‘‘
對yield 的理解