其實一開始並不想學這個用法。可是隨着教材往下看,老是能碰到yield這個東西,致使什麼都看不下去。神煩的不行。因而專門拿出來啃一下html
http://pyzh.readthedocs.org/en/latest/the-python-yield-keyword-explained.html python
這是一篇從stackflow翻譯過來的答案, 很好的解釋了yield。雖是中文,不過我看的時候仍是很吃力的,初學者都這樣吧........哎.......編程
邏輯上來看,想弄懂yield就要懂生成器generator,想懂generator就要懂迭代iteration。ide
(不行,我要吐槽一下,好多網上搜到的資料都是給有必定編程基礎的人寫的,解釋一個命令,就會帶出另一個沒見過的命令或者概念,嵌套嵌套再嵌套,沒完沒了。。。舉例:原本想查一下enumerate的用法,結果碰到yield,查yield,結果碰到xrange,更別提遇到各類帶下劃線的奇怪函數....真是夠了 嗷嗷嗷)函數
吐槽歸吐槽,繼續硬着頭皮學吧。。。post
---------------------------------------------------------------------------------------------------------------------ui
注意:如下內容是上面連接的解釋版。若是看了連接能夠不看這段spa
代碼解釋.net
行1生成一個列表list,這個列表的每一個元素由x的平方組成,x的取值爲range(3),也就是0,1,2。所以這個列表有三個元素:0的平方(0),1的平方(1),2的平方(4)。翻譯
行2打印出這個列表的內容,顯示結果果然是[0,1,4]
行3生成的是一個生成器generator,它和行1惟一的不一樣就是它用的小括號。可是產生的返回值並再也不是一個列表了。那是什麼呢?
行4想要打印出來這個mygen生成器,但結果顯示是這樣的: <generator object <genexpr> at 0x022F8030> 一個內存地址。
怎麼理解這個生成器的概念呢?如上例子所示,其實這個mygen生成器就是用來生成x的平方的東西。這個結果呢就存在上面顯示的內存地址裏。可是因爲你還沒說你到底要誰的平方,因此只能看到個地址不能看到答案。mylist則不一樣,它是把全部答案窮舉列在內存裏了,你須要哪一個就從裏面找出來便可,比較耗費資源。而mygen則還沒生成,你須要哪一個我現製造一個出來放在一個內存空間顯示,節省了資源。(好吧這一段都是我本身的理解....教科書尚未看....)
辣麼,怎麼用這個生成器涅?舉例
這樣就能夠把mygen能夠生成的全部平方數拿出來了。結果顯示:
0
1
4
注意,答案是一個一個蹦出來的,就好像循環讀取同樣。辣麼,當你須要循環讀取、而不是一會兒全顯示出來的時候,用生成器是最好不過的了。
---------------------------------------------------------------------------------------------------------------
若是看上一段內容仍是比較困難的話,咱們再來看下面這段。我找了個新guide,可見: www.cnpythoner.com/post/298.html
---"在python中,當你定義一個函數,使用了yield關鍵字時,這個函數就是一個生成器" (也就是說,只要有yield這個詞出現,你在用def定義函數的時候,系統默認這就不是一個函數啦,是一個生成器啦!!無論裏面內容你寫成神馬樣子 )
--- 通常def定義的函數,都會return一個返回值。而def定義的生成器,返回的則是一個對象,也就是上面提到的相似於「內存地址」的東西。(看來我上面解釋的還不是很對)
--- 若是須要生成器返回(下一個)值,須要調用.next()函數。其實當系統判斷def是生成器時,就會自動支持.next()函數
----------------------------------------------------------------------------------------------------------------
辣麼,咱們來作一個小小的習題,看看是否理解了yield
----------------------------------------------------------------------------------------------------------------
以上是一段關於斐波那契數列的程序。
fib()函數由於含有yield,被系統默認爲是一個生成器。
for語句調用了fib(15)。當max=15時,進入fib()生成器,執行到yield a, 返回a值以及整個生成器暫停的狀態,將a值賦給n, 打印出來;由於是for語句循環,因此又回到fib(15)語句,因爲是生成器,所以從上次截斷的位置開始執行,b值賦給a, a+b值賦給b,又由於是while語句,則繼續while循環,yield a值,循環暫停跳出返回a值及生成器狀態,把a值賦給n, 打印n。如此往復,一直循環到15結束。
m被賦了fib(13)這個生成器,每一次執行m.next()函數就會打印下一個值。
從上面的分析過程,咱們看一下運行結果:
注意:
1. 每一個生成器只能使用一次。好比上個例子中的m生成器,一旦打印完m的6個值,就沒有辦法再打印m的值了,由於已經吐完了。
2. yield通常都在def生成器定義中搭配一些循環語句使用,好比for或者while,以防止運行到生成器末尾跳出生成器函數,就不能再yield了。有時候,爲了保證生成器函數永遠也不會執行到函數末尾,會用while True: 語句,這樣就會保證只要使用next(),這個生成器就會生成一個值,是處理無窮序列的常見方法。