Python基礎(chǔ)手冊(cè)19——迭代器

一、迭代器

我們知道 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è)鍵候学。

字典的 keys() 藕筋、values() 和 items() 方法返回可迭代的視圖對(duì)象,沒有自己的迭代器梳码,它們一次產(chǎn)生一個(gè)結(jié)果項(xiàng)隐圾,而不是在內(nèi)存中一次產(chǎn)生全部結(jié)果列表伍掀。

注意: 在 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ì)記住它們各自的位置怕轿。

相反 zip 對(duì)象偷崩、map 對(duì)象 和 filter 對(duì)象擁有自己的迭代器(可以直接調(diào)用next() 函數(shù)進(jìn)行迭代,不用手動(dòng)調(diào)用 iter() 函數(shù)來(lái)再次生成迭代器)撞羽,不支持相同結(jié)果上的多個(gè)活躍迭代器阐斜。


《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 —— 包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诀紊,隨后出現(xiàn)的幾起案子谒出,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笤喳,死亡現(xiàn)場(chǎng)離奇詭異为居,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)杀狡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門蒙畴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人呜象,你說(shuō)我怎么就攤上這事忍抽。” “怎么了董朝?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵鸠项,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我子姜,道長(zhǎng)祟绊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任哥捕,我火速辦了婚禮牧抽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遥赚。我一直安慰自己扬舒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布凫佛。 她就那樣靜靜地躺著讲坎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愧薛。 梳的紋絲不亂的頭發(fā)上晨炕,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音毫炉,去河邊找鬼瓮栗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瞄勾,可吹牛的內(nèi)容都是我干的费奸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼进陡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼愿阐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起四濒,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤换况,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后盗蟆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戈二,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年喳资,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了觉吭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仆邓,死狀恐怖鲜滩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情节值,我是刑警寧澤徙硅,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站搞疗,受9級(jí)特大地震影響嗓蘑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匿乃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一桩皿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幢炸,春花似錦泄隔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至闸天,卻和暖如春巷燥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背号枕。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工缰揪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人葱淳。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓钝腺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赞厕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艳狐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容