深入淺析Python中的迭代器
目錄結(jié)構(gòu):
contents structure [-]
在開始文章之前,先貼上一張Iterable、Iterator與Generator之間的關(guān)系圖:
1. Iterator VS Iterable
迭代器(Iterator)
迭代器是實(shí)現(xiàn)了迭代器協(xié)議的類對象,迭代器協(xié)議規(guī)定了迭代器類必需定義__next()__方法。當(dāng)對迭代器對象調(diào)用next()方法時,對象會去調(diào)用__next()__計(jì)算迭代器的返回值。
可迭代對象(Iterable)
可迭代對象可以是任何對象,不一定是能返回迭代器的數(shù)據(jù)結(jié)構(gòu)。一個可迭代對象會直接或間接性的調(diào)用這兩個方法__iter()__和__next()__;其中__iter()__方法只能返回迭代器對象,__next()__則供給迭代器進(jìn)行調(diào)用。
通常情況下,可迭代類都會實(shí)現(xiàn)__iter()__和__next()__,并且__iter()__返回它自己,換句話說,該類即是迭代器又是可迭代類。
下面的代碼展示了迭代器和可迭代器對象之間的差別:
a_set = {1, 2, 3}#定義set數(shù)據(jù)類型,set是可迭代類型 b_iterator = iter(a_set)#得到set的迭代器 #Output: 1 print(next(b_iterator)) #Output: <class 'set'> print(type(a_set)) #Output: <class 'set_iterator'> print(type(b_iterator))
從結(jié)果可以看出a_set是一個可迭代類型(set類型),b_iterator是一個迭代器(set_iterator),它們兩個是完全不一同的類型。
下面的自定義了一個迭代器:
class Series(object): def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 n_list = Series(1,10) print(list(n_list))
從上面的代碼可以看出,__iter__返回了迭代器本身。__next__返回迭代器的下一個值,如果沒有下一個返回值那么會拋出StopIteration異常。如果沒有在合適的位置拋出StopIteration異常結(jié)束迭代,那么在某些循環(huán)語句中(例如:for loop),將會形成死循環(huán),所以在__next__中必需要在合適位置添加退出語句(拋出StopIterator異常)。
2.Itertools 模塊
Itertools是Python的內(nèi)置模塊,其中包含了能夠創(chuàng)建迭代器的函數(shù)。簡而言之,它提供了許多能夠與迭代器交互的方法。
下面是我們使用Itertools模塊中count函數(shù)的案例:
from itertools import count sequence = count(start=0, step=1) while(next(sequence) <= 10): print(next(sequence),end=" ")
輸出:
Itertools中的cycle函數(shù)可以創(chuàng)建無限迭代器,例如:
from itertools import cycle dessert = cycle(['Icecream','Cake']) count = 0 while(count != 4): print('Q. What do we have for dessert? A: ' + next(dessert)) count+=1
輸出:
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake
關(guān)于更多itertools模塊的使用, 可以參見python文檔 。
3.生成器(Generator)
生成器可以說是迭代器的親兄弟,生成器允許我們像上面那樣寫迭代器而不用額外定義__iter__()和__next__()方法。
看下面的案例:
def series_generator(low, high): while low <= high: yield low low += 1 n_list = [] for num in series_generator(1,10): n_list.append(num) print(n_list)
如果一個方法中出現(xiàn)了yield關(guān)鍵字,那么該方法就是一個生成器。生成器中沒有return語句,函數(shù)的返回值實(shí)際上是一個generator。當(dāng)循環(huán)開始執(zhí)行到y(tǒng)ield語句后,low的值會被擴(kuò)展到要返回的generator中。當(dāng)下一次循環(huán)到達(dá)yield語句時,generator會從上一次停止的地方恢復(fù)執(zhí)行,并且將最新的low值添加到generator中。循環(huán)一直運(yùn)行下去,直到low>high退出循環(huán)。
生成器支持延遲計(jì)算,只有當(dāng)去取生成器中的值時才會計(jì)算。
例如:
def test(): print("進(jìn)入test函數(shù)") for i in range(2): print("yield number ",i) yield i if "__main__" == __name__: print("開始調(diào)用test") res = test() print("結(jié)束調(diào)用test") next(res) next(res)
輸出:
開始調(diào)用test
結(jié)束調(diào)用test
第一次next(res)
進(jìn)入test函數(shù)
yield number 0
第二次next(res)
yield number 1
從結(jié)果可以看出,只有使用next調(diào)用迭代器時(使用for,while循環(huán)也可以),才會去執(zhí)行迭代器函數(shù)中的內(nèi)容。
python中生成器可以分為生成器函數(shù)和生成器表達(dá)式,生成器函數(shù)和生成器表達(dá)式是兩種不同的類型。
生成器函數(shù)是一個函數(shù)體中有yield關(guān)鍵字的,我們上面定義的test就是生成器函數(shù)。
生成器表達(dá)式的使用比較受限制,一個生成器表達(dá)式返回一個生成器。下面是一個使用生成器表達(dá)式的案例:
squares = (x * x for x in range(1,10)) print(type(squares)) print(list(squares))
輸出:
<class 'generator'>
[1, 4, 9, 16, 25, 36, 49, 64, 81]
生成器的效率是非常高的,生成器可以更好的利用內(nèi)存和CPU的使用效率,并且通常生成器的代碼都比較少,這使用生成器的代碼非常好容易理解。應(yīng)此應(yīng)該盡量多的在代碼中使用生成器
參考文檔
https://www.datacamp.com/community/tutorials/python-iterator-tutorial
總結(jié)
以上所述是小編給大家介紹的Python中的迭代器,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
安裝Python的web.py框架并從hello world開始編程
這篇文章主要介紹了安裝Python的web.py框架并從hello world開始編程,web.py的作者年輕的Aaron Swartz已經(jīng)離世,緬懷大神,需要的朋友可以參考下2015-04-04python實(shí)現(xiàn)AES和RSA加解密的方法
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)AES和RSA加解密的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-03-03安裝出現(xiàn):Requirement?already?satisfied解決辦法
最近pip install的時候報(bào)錯,一大串Requirement already satisfied,所以下面這篇文章主要給大家介紹了關(guān)于安裝出現(xiàn):Requirement?already?satisfied的解決辦法,需要的朋友可以參考下2022-08-08pycharm如何使用anaconda中的各種包(操作步驟)
這篇文章主要介紹了pycharm如何使用anaconda中的各種包,本文通過操作步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07Python基本數(shù)據(jù)類型及內(nèi)置方法
這篇文章主要介紹了Python基本數(shù)據(jù)類型及內(nèi)置方法,??數(shù)據(jù)類型是用來記錄事物狀態(tài)的,而事物的狀態(tài)是不斷變化的,下文圍繞主題展開相關(guān)內(nèi)容需要的小伙伴可以參考一下2022-04-04Python整數(shù)與Numpy數(shù)據(jù)溢出問題解決
這篇文章主要介紹了Python 的整數(shù)與 Numpy 的數(shù)據(jù)溢出,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09python tqdm實(shí)現(xiàn)進(jìn)度條的示例代碼
這篇文章主要介紹了python tqdm實(shí)現(xiàn)進(jìn)度條的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11