標籤:art alt 封裝 lis hid com strong bre filter
一. 什麼是產生器和迭代器
使用一個可迭代的對象比一個列表的好處:
還記得前面的filter和map嗎,他們的傳回值是一個相應的對象,我們可以迴圈這個對象,就取到了每個對象元素,而且取完之後,這個元素就沒啦,一邊取值,一邊記憶體回收,這樣相對於傳回值直接是一個列表,就大大的節省了記憶體。因為如果傳回值是一個長度幾萬幾十萬的列表,會一下子在記憶體裡開闢那麼多的記憶體空間,但是如果產生的是一個filter或者map對象,就沒有這個擔心啦。
我們用一個小例子來進行對比:
1 #要用python2.7的環境 2 #py3中range和xrange合并啦,不再有xrange,range的傳回值是range對象,不再是list 3 4 ret=range(0,10) 5 print ret 6 print type(ret) 7 8 ret=xrange(0,10) 9 print ret10 print type(ret)11 12 執行結果:13 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]14 <type ‘list‘>15 xrange(10)16 <type ‘xrange‘>17 18 #可以明顯看出產生一個可迭代的對象要比產生一個list對記憶體的佔用少的多,xrange的話,取完一個值,用完之後,就會記憶體回收。
range和xrange
產生器就可以實現這個功能。那麼什麼是產生器呢?
產生器是一次產生一個值的特殊類型函數。標誌性的單詞就是yield。
迭代器就是利用next來從產生器裡取資料。
1 def f1(): 2 print("產生第一個數") 3 yield 1 4 print("產生第二個數") 5 yield 2 6 print("產生第三個數") 7 yield 3 8 ret=f1() 9 #執行f1()的時候,3個print都沒有輸出,產生器是一種特殊的函數10 print(ret)11 #產生器產生的ret是一個產生器對象,這個對象可以迭代12 print("*"*10)13 print(list(ret))14 print(list(ret))15 16 執行結果:17 <generator object f1 at 0x102189c50>18 **********19 產生第一個數20 產生第二個數21 產生第三個數22 [1, 2, 3]23 []24 25 def f1():26 print("產生第一個數")27 yield 128 print("產生第二個數")29 yield 230 print("產生第三個數")31 yield 332 ret=f1()33 #產生器可以配合__next__使用34 r1=ret.__next__()35 print(r1)36 #r1:ret.__next__() 會找到函數中的第一個yield,執行函數到這個yield為止,並將yield後面的資料返回37 r2=ret.__next__()38 print(r2)39 #r2:ret.__next__() 會執行上一個yield下面的代碼直到遇到下一個yield,同上會返回yield後面的資料40 41 執行結果:42 產生第一個數43 144 產生第二個數45 2yield
注意:實際使用的時候是不需要我們一個一個的_next_的,for迴圈幫我們做了next,也可以說for迴圈封裝了迭代器。
二. 產生器小例子
1 def zyrange(m,n): 2 while True: 3 yield m 4 m+=1 5 if m == n: 6 break 7 8 for i in zyrange(4,10): 9 print(i)10 11 執行結果:12 413 514 615 716 817 9
使用產生器實現range的功能
python成長之路12——產生器和迭代器