python 生成器和迭代器
1、列表是寫死的,固定的。
a=[0,1,2,3,4,5,6,7,8,9]
print(a)
2、列表生成式會使程式碼更加簡潔
a=[]
for i in range(10):
a.append(i*3)
print(a)
3、列表與列表生成式的執行結果如下:
列表執行結果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
列表生成式執行結果:[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
什麼是生成器
通過列表生成式,我們可以直接建立一個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立一個包含100萬個元素的列表,不僅佔用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為生成器:generator。
如何建立一個生成器
在一個一般函式中使用yield關鍵字,可以實現一個最簡單的生成器,此時這個函式變成一個生成器函式。yield與return返回相同的值,區別在於return返回後,函式狀態終止,而yield會儲存當前函式的執行狀態,在返回後,函式又回到之前儲存的狀態繼續執行。
生成器函式與一般函式的不同
生成器函式包含一個或者多個yield當呼叫生成器函式時,函式將返回一個物件,但是不會立刻向下執行像__iter__()和__next__()方法等是自動實現的,所以我們可以通過next()方法對物件進行迭代一旦函式被yield,函式會暫停,控制權返回呼叫者區域性變數和它們的狀態會被儲存,直到下一次呼叫函式終止的時候,StopIteraion會被自動丟擲生成器如何節省資源?
只記住當前位置,生成器只保留一個值,next之後上一個值就沒有了
只有一個next方法,
#b#__next__()
著名的斐波那契數列
著名的斐波那契數列,除第一個和第二個數外,任意一個數都可由前兩個數相加得到:
1,1,2,3,5,8,13,21,34,...
斐波那契數列用列表生成式寫不出來,但是,用函式把它打印出來卻很容易:
def fib(max): n,a,b=0,0,1 while n<max: print(b) a, b = b, a+b n=n+1 return 'done'f=fib(10)執行結果:
1
1
2
3
5
8
13
21
34
55
想要使它變為生成器,只需要將print(b),改為yiled b即可
def fib(max): n,a,b=0,0,1 while n<max: # print(b) yield b a, b = b, a+b #a = b a = 1,b=2, a=b, a=2 #b = a+b b=2+2=4 n=n+1 return 'done'#異常時列印的訊息執行結果:通過使用next的方式進行取值
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
使用for迴圈那個return的down是無法列印的
for i in f:
print(i)
使用next方法取資料取不出來了,就會丟擲一個異常
Traceback (most recent call last):
File "D:\python\index.py", line 85, in <module>
print(f.__next__())
StopIteration: done
如何處理異常,可通過抓取異常
g=fib(6)
#異常處理程式碼
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
最終執行結果:
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
===start loop===
為什麼使用生成器
更容易使用,程式碼量較小記憶體使用更加高效。比如列表是在建立的時候就分配所有的記憶體空間,而生成器僅僅是需要的時候才使用,更像一個記錄代表了一個無限的流。如果我們要讀取並使用的內容遠遠超過記憶體,但是需要對所有的流中的內容進行處理,那麼生成器是一個很好的選擇,比如可以讓生成器返回當前的處理狀態,由於它可以儲存狀態,那麼下一次直接處理即可。流水線生成器。假設我們有一個快餐記錄,這個記錄的地4行記錄了過去五年每小時售出的食品數量,並且我們要把所有的數量加在一起,求解過去5年的售出的總數。假設所有的資料都是字串,並且不可用的數字被標記成N/A。那麼可以使用下面的方式處理:結語
感謝閱讀,歡迎在評論區中發表自己不同的觀點,若有其他問題請在評論區留言,喜歡的朋友請多多關注轉發支援一