|
【要點(diǎn)搶先看】
【妹子說】這一節(jié)的標(biāo)題名稱看起來比較陌生啊。 對,這一節(jié)很pythonic,是很有特色也非常重要的知識點(diǎn)。敲黑板! Python中有一類工具叫做迭代工具,他們能從左至右掃描對象。這包括了for循環(huán)、列表解析、in成員關(guān)系測試以及map內(nèi)置函數(shù)等。 而可迭代對象,顧名思義就是可以用在上述迭代工具環(huán)境中,通過一次次迭代不斷產(chǎn)生結(jié)果的對象。 可迭代對象分為兩大類,一種是實(shí)際保存的序列,即列表、元組,字符串;另一種就是我們上一節(jié)總提到的“不一次性產(chǎn)生所有結(jié)果列表,而是可以在for循環(huán)中按需一次產(chǎn)生一個(gè)結(jié)果的對象”。如:range函數(shù)返回值、zip函數(shù)返回值、enumerate函數(shù)返回值等等,與實(shí)際序列相對應(yīng),這個(gè)叫做按需產(chǎn)生對象的虛擬序列。 我們注意到,這一小節(jié)的標(biāo)題中還有一個(gè)詞叫做迭代器,他倆放在一起容易把人弄迷糊,他們之間的關(guān)系,相信你看完下面一段介紹就會很清楚了: 可迭代對象支持內(nèi)置函數(shù)iter,通過對可迭代對象調(diào)用iter函數(shù),會返回一個(gè)迭代器,而“迭代器”支持內(nèi)置函數(shù)next,通過不斷對其調(diào)用next方法,會依次前進(jìn)到序列中的下一個(gè)元素并將其返回,最后到達(dá)一系列結(jié)果的末尾時(shí),會引發(fā)StopIteration異常。補(bǔ)充說明一點(diǎn),對迭代器調(diào)用iter方法,則會返回迭代器自身。 L = [2,3,4]從這個(gè)例子中我們看到,通過iter函數(shù)將迭代對象轉(zhuǎn)化成迭代器,而對迭代器調(diào)用iter函數(shù),依然返回迭代器。 我們來完整的看看迭代過程是怎么實(shí)現(xiàn)的:當(dāng)任何可迭代對象傳入到for循環(huán)或其他迭代工具中進(jìn)行遍歷時(shí),迭代工具都是先通過iter函數(shù)獲得與可迭代對象對應(yīng)的迭代器,然后再對迭代器調(diào)用next函數(shù),不斷的依次獲取元素,并在捕捉到StopIteration異常時(shí)確定完成迭代,這就是完整的迭代過程。這也稱之為“迭代協(xié)議”。 還是舉例子說明,我們來模擬for循環(huán)如何處理內(nèi)置可迭代對象-----內(nèi)置類型列表L: L = [2,3,4]在這個(gè)手動模擬迭代的過程中,先把可迭代對象轉(zhuǎn)換成迭代器,然后用next方法進(jìn)行手動迭代,迭代到最后出現(xiàn)StopIteration異常退出。 與手動迭代的示例過程相對應(yīng),下面是用for循環(huán)進(jìn)行自動迭代的過程,這個(gè)大家都很熟悉。 L = [2,3,4]再舉幾個(gè)典型的例子 文件對象 open函數(shù)返回的已打開的文件對象,也是可以一行一行的讀取,直至文件結(jié)束,那很顯然,他也是可迭代對象。 f = open('myfile.txt')從這個(gè)例子中我們可以看出,文件對象的迭代器就是他自己。即文件對象既是迭代器,又是可迭代對象。我們還是用上面的手動模擬迭代的方式來一探究竟 f = open('myfile.txt')對應(yīng)的,直接用for循環(huán)來進(jìn)行自動迭代 f = open('myfile.txt')之前我們提到過,這是讀取文件的最佳方式,首先是簡單、運(yùn)行速度快,并且從內(nèi)存使用情況而言也是最好的。讓我們對比一下較為原始的readlines方法, f = open('myfile.txt')對比來看,雖然readlines方法在功能上可用,但從內(nèi)存上來看,非常糟糕,他是一次性把整個(gè)文件加載到內(nèi)存,如果文件太大,以至于計(jì)算機(jī)內(nèi)存不夠,甚至不能夠工作。而我們的迭代器版本則不然,迭代器是按需,一次只讀取一行,因此對內(nèi)存爆炸問題有了很好的免疫。 字典類型 文件和列表對象都是實(shí)際的序列,他所迭代的就是他的實(shí)際內(nèi)容,那字典呢?字典也是一種可迭代對象,但是他的迭代器卻比較特殊。我們看看手動模擬迭代過程的例子: D = {'a':1, 'b':2, 'c':3}同樣,在for循環(huán)中自動迭代的例子如下: D = {'a':1, 'b':2, 'c':3}因此不難看出,字典也是一個(gè)可迭代對象,字典有一個(gè)迭代器,在迭代環(huán)境中,會每次自動地返回一個(gè)鍵。 而需要補(bǔ)充的是,字典擁有不同視圖的可迭代對象,這里就不詳細(xì)一一展開了,看看幾個(gè)例子,分別是各自不同視圖下的可迭代對象和迭代器,他們也是一次產(chǎn)生一個(gè)結(jié)果項(xiàng),而不是在內(nèi)存中一次產(chǎn)生全部結(jié)果列表。 D = {'a':1,'b':2,'c':3}再舉兩個(gè)我們上一節(jié)提到的例子:range函數(shù)和enumerate函數(shù) range函數(shù)的返回值是一個(gè)可迭代對象,同理利用iter方法也可以得到他的迭代器 R = range(5)enumerate方法返回的也是可迭代對象,他的迭代器就是他自身 E = enumerate('spam')可迭代對象按照需求,一次只返回一個(gè)結(jié)果,而不是一口氣一次性的返回一個(gè)對象列表,因此我們必須把可迭代對象包裹在一個(gè)list調(diào)用中,從而才能一次性看到它們所有的值。 print(list(enumerate('spam'))) |
|
|