1. 程式人生 > >對yield 的理解

對yield 的理解

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 的理解