python 中 yield 用法的總結(jié)

在MPGI4的第二次作業(yè)中,出現(xiàn)了 xrange() 相關(guān)用法,在查找其與 range 有什么不同時,發(fā)現(xiàn)了 generatoryield 等一系列概念,特此總結(jié)。


yield 的用法起源于對一般 functionreturn 的擴(kuò)展。在一個 function 中,必須有一個返回值列于 return 之后,可以返回數(shù)字也可以返回空值,但是必須要有一個返回值,標(biāo)志著這個 function 的結(jié)束。一旦它結(jié)束,那么這個 function 中產(chǎn)生的一切變量將被統(tǒng)統(tǒng)拋棄,有什么可以使一個 function 暫停下來,并且返回當(dāng)前所在地方的值,當(dāng)接收到繼續(xù)的命令時可以繼續(xù)前進(jìn)呢?換個說法,就是 return 返回一個值,并且記住這個返回的位置。這個操作有點兒像

for x in range():
    pass

這個循環(huán)語句中 range() 這個函數(shù)干的事情,它給出一個數(shù),當(dāng)循環(huán)完一次以后再在前一個數(shù)的基礎(chǔ)上拿出另外一個數(shù)。但是這里的函數(shù)其實是自動生成一個 list 然后從這個 list 第一個開始往后一個一個給出,那么這種方法的劣勢顯而易見——會有生成一個 list 。也就是說不管你的 for 循環(huán)用幾回,它都會生成這個 list (比如你有一個龐大的數(shù)據(jù)庫,那么光是生成一個表單就需要很長時間,然而也許你要用的東西就在前幾個,那么你建起這個檢索目錄遠(yuǎn)遠(yuǎn)超過你實際所需要的)。這時就是 xrange() 登場的時候了,它就是一個不需要建立 list 卻一樣完成任務(wù)的好命令。那么 xrange() 是什么呢?

xrange() 其實是一個 generator 生成器,不同于一般的 function,里面就包含著yield。generator 人如其名,是一個生成器,生成什么呢?不妨把它看作生成一組你需要的序列的函數(shù),通常情況下我們只需要自然數(shù)這種簡單的序列,但是如果讓你生成一組斐波那契數(shù)列呢?這組數(shù)列是無窮的,你想沿著這個數(shù)列一直算下去,直到算到你滿意的一個數(shù),但是如果你也不知道這個數(shù)在哪里,那么你就不能提前給出一個這個數(shù)列,因為你不知道在哪里會停下來。面對這個問題時,最好的解決方法就是記住當(dāng)前的數(shù),記住當(dāng)前的地址,查看一個這個數(shù)符合不符合要求,如果不符合要求,那么繼續(xù)從這個數(shù)/地址開始計算下一個斐波那契數(shù)字。這就是 yield 要干的事情了。(其實這么做的好處還有一個就是減少斐波那契數(shù)列的運(yùn)算量,這個數(shù)列因為是自循環(huán)數(shù)列,所以如果按照循環(huán)算法的話需要很大的運(yùn)算量,但是如果是采用動態(tài)紀(jì)錄法的話,那么就會非常簡單。這屬于優(yōu)化算法范疇,暫且按下不表。)下面就是斐波那契數(shù)列用 yield 的實現(xiàn)法:

# 斐波那契數(shù)列:每一個數(shù)都等于前兩個數(shù)之和
def fib(to=10):
    curr = 0
    next = 1
    count = 0
    while count < to:
        yield curr
        curr = next
        next = curr + next
        count += 1

# 一個用法例子:每一個斐波那契數(shù)列的數(shù)加1
if __name__ == '__main__':
    for x in fib(20):
        print(x+1)
        
    

注意:yield 一旦被采用,那么def后面的代碼會立馬被認(rèn)作是一個 generator 而不是一個 function,因為生成的是一個 generator,所以可以被用在 for in 這個循環(huán)語句中。而 generatorfunction 從本質(zhì)上是不同的,兩者的區(qū)別就涉及到了next()send()這兩個函數(shù)的用法。

如果把這個python文件命名為fi.py,并運(yùn)行之。那么可以瞬間得到結(jié)果:

?  Desktop  python fi.py
1
2
3
5
9
17
33
65
129
257
513
1025
2049
4097
8193
16385
32769
65537
131073
262145

用這個方法可以自己研究很多有趣的數(shù)學(xué)問題,比如找出2萬以內(nèi)的質(zhì)數(shù)之和,找出大于10的0次方,一次方,...,n次方的最小質(zhì)數(shù)。你不需要建立一個很大的索引庫,只需要一個一個數(shù)字算下去就好。

這篇Jeff的文章幫了我一些忙,但可能是我英語不好,雖然解釋的很基礎(chǔ),但對于我來說,還是沒有徹底理解yield 和與其配套的next()send()的用法,以至于我拼命想搞懂他們的用法和關(guān)系并且成功了,不過回過頭來看,確實解釋的很全面。我覺得這種基礎(chǔ)全面式解釋需要一個實際的用法例子來補(bǔ)充說明,從稍微高一點兒的地方,或者從另一個初學(xué)者的視角來解釋他們,初學(xué)者并不要解釋的太基礎(chǔ),因為初學(xué)者其實學(xué)編程語言時根本不基礎(chǔ),越往后學(xué)習(xí)才會涉及到編譯器的某些基礎(chǔ)概念,這也是這篇文章的立意之處。

未完待續(xù):next()send()這兩個函數(shù)的用法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在此處先列下本篇文章的主要內(nèi)容 簡介 next方法的參數(shù) for...of循環(huán) Generator.prototy...
    醉生夢死閱讀 1,488評論 3 8
  • 簡介 基本概念 Generator函數(shù)是ES6提供的一種異步編程解決方案,語法行為與傳統(tǒng)函數(shù)完全不同。本章詳細(xì)介紹...
    呼呼哥閱讀 1,136評論 0 4
  • 特別說明,為便于查閱,文章轉(zhuǎn)自https://github.com/getify/You-Dont-Know-JS...
    殺破狼real閱讀 501評論 0 0
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點點福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 1,091評論 0 0
  • https://www.ibm.com/developerworks/cn/opensource/os-cn-py...
    吳燁JS閱讀 594評論 0 0

友情鏈接更多精彩內(nèi)容