最近在學習Python的時候看到yield的相關語法,感受很獨特,相比其餘如C/C++的語法比較有意思,因而在看完資料相關章節作一個總結。dom
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)
結果:spa
''' 4 3 2 1 0 '''
這種獨特語法現象的緣由,從書中摘出相關資料以下:設計
當函數中使用yield產生一個值的時候,調用函數會返回一個generator對象,也就是一個生成器,此對象有__next__()方法,一般會調用next()調用該方法取出下一個產生的值,若沒法產生下一個值,就會發生StopIteration這樣的異常 --《Python程序設計教程》code
除了解釋以上現象,反之也可推測 for in 函數的參數能夠是生成器,生成器具備惰性求值特色,推測以前遇到過惰性求值的都是生成器(推測)orm
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,而沒有任何輸出,彷佛是沒用,可是刪除以後程序卻沒法執行,個人理解是必須執行一次使值轉化成生成器對象才能接受相關數據。blog
爲了印證個人觀點,執行如下代碼:教程
print(type(producer)) print(type(producer()))
輸出:
''' <class 'function'> <class 'generator'> '''