一、迭代器
我們知道 for 循環(huán)可以用于 Python 中的任何序列類型腹暖,實(shí)際上 for 循環(huán)可用于Python 中的任何可迭代類型刻像。對(duì)于 Python 中所有會(huì)從左至右掃描對(duì)象的迭代工具而言都是如此,這些迭代工具包括了 for 循環(huán)国觉、列表解析酒贬、in 成員關(guān)系測(cè)試以及 map() 內(nèi)置函數(shù)等,他們都支持任何的可迭代類型翠霍。
”可迭代對(duì)象“ 的概念在 Python 中基本上和序列概念是一樣的:如果對(duì)象是實(shí)際保存的序列锭吨,或者可以在迭代工具環(huán)境中(例如,for循環(huán))一次產(chǎn)生一個(gè)結(jié)果的對(duì)象寒匙,就看做這個(gè)對(duì)象是可迭代的零如。總之锄弱,可迭代對(duì)象包括實(shí)際序列和按照需求而計(jì)算的虛擬序列(比如:range對(duì)象 和 生成器函數(shù))考蕾。
1、迭代協(xié)議: next()
文件對(duì)象有一個(gè)方法 __next__() 会宪,每次調(diào)用時(shí)肖卧,就會(huì)返回文件的下一行,到達(dá)文件末尾時(shí)掸鹅, __next__() 會(huì)引發(fā)內(nèi)置的 StopInteration 異常塞帐。
這個(gè)接口就是Python中的迭代協(xié)議:有一個(gè) __next__() 方法的對(duì)象在迭代工具的依次迭代中會(huì)依次的前進(jìn)到下一個(gè)結(jié)果拦赠,而在一系列結(jié)果的末尾時(shí),則會(huì)引發(fā)StopInteration 異常葵姥。在Python中荷鼠,任何這類對(duì)象都認(rèn)為是可迭代的。任何這類對(duì)象也能以 for 循環(huán)或其他迭代工具遍歷榔幸,因?yàn)樗械牡ぞ邇?nèi)部工作起來(lái)都是在每次迭代中調(diào)用可迭代對(duì)象的 __next__() 方法允乐,并且捕捉 StopInteration 異常來(lái)確定何時(shí)離開。
所以逐行讀取文本文件的最佳方法就是根本不要去讀取削咆,而是讓 for 循環(huán)在每次迭代中自動(dòng)調(diào)用文件對(duì)象的 __next__() 方法從而前進(jìn)到下一行牍疏。這里的 print() 使用 end='' 參數(shù)來(lái)抑制自動(dòng)添加一個(gè) '\n',因?yàn)樽址呀?jīng)有一個(gè)(如果 print() 再自動(dòng)加上一個(gè)态辛,我們的輸出將會(huì)多輸出一個(gè)空行)麸澜。
上面是讀取文本文件的最佳方式,因?yàn)檫@是代碼最簡(jiǎn)單奏黑、運(yùn)行最快的方法炊邦,并且從內(nèi)存使用情況來(lái)說(shuō)也是最好的。迭代器在 Python 中是以 C 語(yǔ)言的速度運(yùn)行的熟史,而 while 循環(huán)則是通過(guò) Python 虛擬機(jī)運(yùn)行 Python 字節(jié)碼的馁害。所以我們一直建議在能夠使用 for 循環(huán)的時(shí)候都使用 for 循環(huán),因?yàn)樗褂酶奖沲迤ィ\(yùn)行更高效碘菜。
2、內(nèi)置函數(shù):next() 和 iter()
為了更方便的手動(dòng)迭代可迭代對(duì)象限寞,Python 3.0 還提供了一個(gè)內(nèi)置函數(shù) next() 忍啸,它會(huì)自動(dòng)調(diào)用一個(gè)對(duì)象的 __next__() 方法。也就是說(shuō)對(duì)于一個(gè)可迭代對(duì)象履植,使用 next() 內(nèi)建函數(shù)調(diào)用和調(diào)用其 __next__() 方法是一樣的计雌,但是前者要簡(jiǎn)單很多。
當(dāng) for 循環(huán)開始時(shí)玫霎,會(huì)將對(duì)象傳給 iter() 內(nèi)置函數(shù)凿滤,以便從可迭代對(duì)象中獲得一個(gè)迭代器,返回的對(duì)象含有需要的 __next__() 方法庶近。
對(duì)于文件對(duì)象來(lái)說(shuō)是不需要調(diào)用 iter() 函數(shù)的翁脆,因?yàn)槲募?duì)象擁有自己的迭代器。也就是說(shuō)鼻种,文件對(duì)象有自己的 __next__() 方法反番。
列表以及很多其他的內(nèi)置對(duì)象,自身沒有 __next__() 方法,也就是沒有自身的迭代器恬口,但是它們支持多次打開(創(chuàng)建)迭代器校读。對(duì)于這樣的對(duì)象,我們必須調(diào)用 iter() 函數(shù)來(lái)為他們創(chuàng)建迭代器祖能,啟動(dòng)迭代歉秫。盡管Python的迭代工具自動(dòng)調(diào)用這些函數(shù),我們也可以使用它們來(lái)手動(dòng)地應(yīng)用迭代協(xié)議养铸。
3雁芙、其他迭代環(huán)境
在 Python 的內(nèi)置工具集中從左至右掃描一個(gè)對(duì)象的每項(xiàng)工具都定義為在對(duì)象上使用了迭代協(xié)議。列表解析钞螟、in 成員關(guān)系測(cè)試兔甘、map() 內(nèi)置函數(shù)以及像 sorted() 和 zip() 調(diào)用這樣的內(nèi)置函數(shù)也都使用了迭代協(xié)議,所有這些都接收一個(gè)可迭代的對(duì)象鳞滨。
Python還包含了各種處理迭代的其他內(nèi)置函數(shù):
- sorted() 排序洞焙,可迭代對(duì)象中的各項(xiàng);
- zip() 組合拯啦,可迭代對(duì)象中的各項(xiàng)澡匪;
- enumerate() 根據(jù)相對(duì)位置來(lái)配對(duì),可迭代對(duì)象中的各項(xiàng)褒链,
- filter() 選擇一個(gè)函數(shù)為真的項(xiàng)唁情;
- reduce() 針對(duì)可迭代對(duì)象中的成對(duì)的項(xiàng)運(yùn)行一個(gè)函數(shù)。
二甫匹、Python 3.0 中的可迭代對(duì)象
Python 3.0 中的一個(gè)基本改變是甸鸟,它更強(qiáng)調(diào)迭代。除了與文件和序列這樣的內(nèi)置類型相關(guān)的迭代兵迅,字典本身抢韭,以及字典的方法 keys(),values() 和 items() 都在 Python 3.0 中返回可迭代對(duì)象恍箭,就像內(nèi)置函數(shù) range()刻恭、map()、zip() 和 filter() 所做的那樣季惯。
1吠各、字典
在Python3.0 中臀突,字典對(duì)象也支持創(chuàng)建自己的迭代器勉抓,在迭代環(huán)境中,會(huì)自動(dòng)一次返回一個(gè)鍵候学。注意: 在 Python 3.0 中字典對(duì)象是可迭代的(沒有自己的迭代器),它返回連續(xù)的鍵暇藏。因此無(wú)需直接在此環(huán)境中調(diào)用 keys() 方法蜜笤,而且這樣由于中間生成了dict_keys對(duì)象,還會(huì)導(dǎo)致執(zhí)行效率的下降盐碱。
2把兔、range() 內(nèi)置函數(shù)
它返回一個(gè)可迭代的 range 類型對(duì)象,range 對(duì)象根據(jù)需要產(chǎn)生范圍中的數(shù)字瓮顽,而不是在內(nèi)存中構(gòu)建一個(gè)結(jié)果列表县好。在 Python 3.0 中 range 對(duì)象只支持迭代、索引以及 len() 函數(shù)暖混。他不支持任何其他的序列操作缕贡。
3、map()拣播、zip() 和 filter() 內(nèi)置函數(shù)
和 range() 類似晾咪,map()、zip() 和 filter() 內(nèi)置函數(shù)在 Python 3.0 中也返回可迭代對(duì)象以節(jié)約內(nèi)存空間诫尽,而不在內(nèi)存中一次性生成一個(gè)結(jié)果列表禀酱。
和 range() 不同,它們都擁有自己的迭代器——在遍歷其結(jié)果一次以后牧嫉,它們就用盡了剂跟。換句話說(shuō),不能在它們的結(jié)果上擁有那些在結(jié)果中保持不同位置的多個(gè)迭代器酣藻。4曹洽、多個(gè)迭代器 VS 單個(gè)迭代器
range 對(duì)象沒有自己的迭代器(手動(dòng)迭代時(shí),我們使用 iter() 辽剧,為 range 對(duì)象生成一個(gè)迭代器)送淆,并且它支持在其結(jié)果上創(chuàng)建多個(gè)迭代器,這些迭代器會(huì)記住它們各自的位置怕轿。《Python基礎(chǔ)手冊(cè)》系列:
Python基礎(chǔ)手冊(cè) 1 —— Python語(yǔ)言介紹
Python基礎(chǔ)手冊(cè) 2 —— Python 環(huán)境搭建(Linux)
Python基礎(chǔ)手冊(cè) 3 —— Python解釋器
Python基礎(chǔ)手冊(cè) 4 —— 文本結(jié)構(gòu)
Python基礎(chǔ)手冊(cè) 5 —— 標(biāo)識(shí)符和關(guān)鍵字
Python基礎(chǔ)手冊(cè) 6 —— 操作符
Python基礎(chǔ)手冊(cè) 7 —— 內(nèi)建函數(shù)
Python基礎(chǔ)手冊(cè) 8 —— Python對(duì)象
Python基礎(chǔ)手冊(cè) 9 —— 數(shù)字類型
Python基礎(chǔ)手冊(cè)10 —— 序列(字符串)
Python基礎(chǔ)手冊(cè)11 —— 序列(元組&列表)
Python基礎(chǔ)手冊(cè)12 —— 序列(類型操作)
Python基礎(chǔ)手冊(cè)13 —— 映射(字典)
Python基礎(chǔ)手冊(cè)14 —— 集合
Python基礎(chǔ)手冊(cè)15 —— 解析
Python基礎(chǔ)手冊(cè)16 —— 文件
Python基礎(chǔ)手冊(cè)17 —— 簡(jiǎn)單語(yǔ)句
Python基礎(chǔ)手冊(cè)18 —— 復(fù)合語(yǔ)句(流程控制語(yǔ)句)
Python基礎(chǔ)手冊(cè)19 —— 迭代器
Python基礎(chǔ)手冊(cè)20 —— 生成器
Python基礎(chǔ)手冊(cè)21 —— 函數(shù)的定義
Python基礎(chǔ)手冊(cè)22 —— 函數(shù)的參數(shù)
Python基礎(chǔ)手冊(cè)23 —— 函數(shù)的調(diào)用
Python基礎(chǔ)手冊(cè)24 —— 函數(shù)中變量的作用域
Python基礎(chǔ)手冊(cè)25 —— 裝飾器
Python基礎(chǔ)手冊(cè)26 —— 錯(cuò)誤 & 異常
Python基礎(chǔ)手冊(cè)27 —— 模塊
Python基礎(chǔ)手冊(cè)28 —— 模塊的高級(jí)概念
Python基礎(chǔ)手冊(cè)29 —— 包