對yield 的理解

  最近在學習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'>

'''
相關文章
相關標籤/搜索