生成器(generator)概念
生成器不會把結果保存在一個系列中,而是保存生成器的狀態,在每次進行迭代時返回一個值,直到遇到StopIteration異常結束。
生成器語法
生成器表達式: 通列表解析語法,只不過把列表解析的[]換成()
生成器表達式能做的事情列表解析基本都能處理,只不過在需要處理的序列比較大時,列表解析比較費內存。
>>> gen = (x**2 for x in range(5))>>> gen<generator object <genexpr> at 0x0000000002FB7B40>>>> for g in gen:... print(g, end='-')...0-1-4-9-16->>> for x in [0,1,2,3,4,5]:... print(x, end='-')...0-1-2-3-4-5-
生成器函數: 在函數中如果出現了yield關鍵字,那么該函數就不再是普通函數,而是生成器函數。
但是生成器函數可以生產一個無線的序列,這樣列表根本沒有辦法進行處理。
yield 的作用就是把一個函數變成一個 generator,帶有 yield 的函數不再是一個普通函數,Python 解釋器會將其視為一個 generator。
下面為一個可以無窮生產奇數的生成器函數。
defodd():n=1whileTrue:yieldnn+=2odd_num=odd()count=0foroinodd_num:ifcount>=5:breakprint(o)count+=1
當然通過手動編寫迭代器可以實現類似的效果,只不過生成器更加直觀易懂
class Iter: def __init__(self): self.start=-1 def __iter__(self): return self def __next__(self): self.start +=2 return self.startI = Iter()for count in range(5): print(next(I))
題外話: 生成器是包含有__iter()和next__()方法的,所以可以直接使用for來迭代,而沒有包含StopIteration的自編Iter來只能通過手動循環來迭代
>>>fromcollectionsimportIterable>>>fromcollectionsimportIterator>>>isinstance(odd_num,Iterable)True>>>isinstance(odd_num,Iterator)True>>>iter(odd_num)isodd_numTrue>>>help(odd_num)Helpongeneratorobject:odd=classgenerator(object)| Methodsdefinedhere:|| __iter__(self,/)| Implementiter(self).|| __next__(self,/)| Implementnext(self).......
到上面的結果,現在你可以很有信心的按照Iterator的方式進行循環了吧!
在 for 循環執行時,每次循環都會執行 fab 函數內部的代碼,執行到 yield b 時,fab 函數就返回一個迭代值,下次迭代時,代碼從 yield b 的下一條語句繼續執行,而函數的本地變量看起來和上次中斷執行前是完全一樣的,于是函數繼續執行,直到再次遇到 yield。看起來就好像一個函數在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。
yield 與 return
在一個生成器中,如果沒有return,則默認執行到函數完畢時返回StopIteration;
新聞熱點
疑難解答