python筆記--迭代器和生成器

迭代器

迭代器協(xié)議:

對象需要提供next()方法,它要么返回迭代中的下一項,要么就引起一個StopIteration異常,以終止迭代。

可迭代對象:

實現(xiàn)了迭代器協(xié)議對象。list、tuple、dict都是Iterable(可迭代對象),但不是iteration(迭代器對象)。但可以使用內(nèi)建函數(shù)iter(),把這些都變成iteration(迭代器對象)。

為什么在python中,文件還可以使用for循環(huán)進行遍歷呢?這是因為,在python中,文件對象實現(xiàn)了迭代器協(xié)議,for循環(huán)并不知道它遍歷的是一個文件對象,它只管使用迭代器協(xié)議訪問對象即可。正是由于python的文件對象實現(xiàn)了迭代器協(xié)議,我們才得以使用如此方便的方式訪問文件,如下所示:

>>>hasattr(open(__file__),'__iter__')

True

為什么list、dict、str等數(shù)據(jù)類型不是Iterator?

1.Python的Iterator對象表示的是一個數(shù)據(jù)流,雖然這個數(shù)據(jù)流看做是一個有序序列,但是元素的獲得只能通過next(),因為Iterator的計算是惰性的,只有在需要返回下一個數(shù)據(jù)時它才會計算。

2.而list、dict、str等數(shù)據(jù)類型,提供了對元素更加方便的操作,可以直接獲取元素,提前知道序列的長度。

3.但是,iterator也有好處,它可以表示一個無限大的數(shù)據(jù)流,例如全體自然數(shù)。而使用list是永遠不可能存儲全體自然數(shù)的。

生成器

1.兩種產(chǎn)生方式:

①生成器函數(shù):

常規(guī)函數(shù)定義,但是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每個結果中間,掛起函數(shù)的狀態(tài),以便下次從它離開的地方繼續(xù)執(zhí)行

defhello():

? ? ?for i in ?range(3):

? ? ? ? ? yield i*i

for i ?in ?hello():

? ? print ?i

注意:在函數(shù)hello被調(diào)用的時候,返回的是生成器;只有在第一次next()的時候才會從頭執(zhí)行函數(shù)直到碰到y(tǒng)ield,之后繼續(xù)從上次yield這一句之后繼續(xù)執(zhí)行,直到不滿足條件,沒有值可以獲得。

②生成器表達式:

類似于列表推導,只不過是把一對大括號[]變換為一對小括號()。但是,生成器表達式是按需產(chǎn)生一個生成器結果對象,要想拿到每一個元素,就需要循環(huán)遍歷。

>>>gen = (i*i for i in range(3))

2.好處

①延遲操作。也就是在需要的時候才產(chǎn)生結果,不是立即產(chǎn)生結果。

例如:

print sum( [ i for i in range(10000000000) ?])

print sum( i ? for i in range(10000000000) ? )

第一種方式很容易出現(xiàn)電腦卡死,因為會一次性將list中的內(nèi)容加載到內(nèi)存中

②簡化代碼,提高代碼可讀性

def ?hello(text):

? ? ? ?result = []

? ? ? ?if ? ?text:

? ? ? ? ? ? ? result.append(0)

? ? ? ?for ?index,letter in enumerate(text,1):

? ? ? ? ? ? ? if ?letter ==' ':

? ? ? ? ? ? ? ? ? ? result.append(index)

? ? ? ?return ? result

def ?hello(text):

? ? ? ? if ? ?text:

? ? ? ? ? ? ? ?yield0

? ? ? ? for ?index,letter ? ?in ?enumerate(text,1):

? ? ? ? ? ? ? if ? ?letter ==' ':

? ? ? ? ? ? ? ? ? ? yield index

注意:不使用生成器的時候,對于每次結果,我們首先看到的是result.append(index),其次,才是index。也就是說,我們每次看到的是一個列表的append操作,只是append的是我們想要的結果。使用生成器的時候,直接yield index,少了列表append操作的干擾,我們一眼就能夠看出,代碼是要返回index。

3.注意事項

生成器只能遍歷一次,第二次遍歷的時候返回空

4.深入理解

①與函數(shù)比較:生成器函數(shù)和常規(guī)函數(shù)幾乎是一樣的。它們都是使用def語句進行定義,差別在于,生成器使用yield語句返回一個值,而常規(guī)函數(shù)使用return語句返回一個值。

與迭代器關系:會自動實現(xiàn)迭代器協(xié)議,以便應用到迭代背景中(如for循環(huán),sum函數(shù))。由于生成器自動實現(xiàn)了迭代器協(xié)議,所以,我們可以調(diào)用它的next方法,并且,在沒有值可以返回的時候,生成器自動產(chǎn)生StopIteration異常。生成器是一種迭代器

③掛起狀態(tài):生成器使用yield語句返回一個值。yield語句掛起該生成器函數(shù)的狀態(tài),保留足夠的信息,以便之后從它離開的地方繼續(xù)執(zhí)行

5.應用場景:

1.你不需要重復讀這些值

2.你可能有海量的子節(jié)點,但是不希望將所有節(jié)點放入內(nèi)存

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容