Python中的yield

Python中的yield

其實一開始並不想學這個用法。可是隨着教材往下看,老是能碰到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

 

[python]  view plain  copy
 
  1. mylist = [x*x for x in range(3)]  
  2. print mylist  
  3. mygen=(x*x for x in range(3))  
  4. print mygen  

 

 

代碼解釋.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則還沒生成,你須要哪一個我現製造一個出來放在一個內存空間顯示,節省了資源。(好吧這一段都是我本身的理解....教科書尚未看....)

 

辣麼,怎麼用這個生成器涅?舉例

 

[python]  view plain  copy
 
  1. mygen=(x*x for x in range(3))  
  2. for i in mygen:  
  3.     print (i)  


這樣就能夠把mygen能夠生成的全部平方數拿出來了。結果顯示:

 

0

1

4

注意,答案是一個一個蹦出來的,就好像循環讀取同樣。辣麼,當你須要循環讀取、而不是一會兒全顯示出來的時候,用生成器是最好不過的了。

---------------------------------------------------------------------------------------------------------------

若是看上一段內容仍是比較困難的話,咱們再來看下面這段。我找了個新guide,可見: www.cnpythoner.com/post/298.html

---"在python中,當你定義一個函數,使用了yield關鍵字時,這個函數就是一個生成器" (也就是說,只要有yield這個詞出現,你在用def定義函數的時候,系統默認這就不是一個函數啦,是一個生成器啦!!無論裏面內容你寫成神馬樣子 )

--- 通常def定義的函數,都會return一個返回值。而def定義的生成器,返回的則是一個對象,也就是上面提到的相似於「內存地址」的東西。(看來我上面解釋的還不是很對)

--- 若是須要生成器返回(下一個)值,須要調用.next()函數。其實當系統判斷def是生成器時,就會自動支持.next()函數

 

[python]  view plain  copy
 
  1. c = h() #h()包含了yield關鍵字    
  2. print  c.next() #返回值   

 

----------------------------------------------------------------------------------------------------------------

辣麼,咱們來作一個小小的習題,看看是否理解了yield

----------------------------------------------------------------------------------------------------------------

 

[python]  view plain  copy
 
  1. def fib(max):  
  2.     a, b = 1, 1  
  3.     while a < max:  
  4.         yield a  
  5.         a, b = b, a+b  
  6.   
  7. for n in fib(15):  
  8.     print n  
  9.   
  10. m = fib(13)  
  11. print m  
  12. print m.next()  
  13. print m.next()  
  14. print m.next()  


以上是一段關於斐波那契數列的程序。

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(),這個生成器就會生成一個值,是處理無窮序列的常見方法。

相關文章
相關標籤/搜索