Python-迭代器相關(guān)概念

各概念關(guān)系圖

一些基本概念


1 容器

可以詢問某個元素是否包含其中类垦,如list磨澡,set,tuples,dict等都是容器

2 迭代器(iterator)


1)迭代器是一個帶狀態(tài)的對象指巡,任何實現(xiàn)了iter和next__方法的對象都是迭代器(python2:任何實現(xiàn)next()方法的對象都是迭代器)。
2)其中iter返回迭代器本身隶垮,next返回容器中的下一個值藻雪。如果容器中沒有更多元素了,則拋出Stopiteration異常狸吞。

因此勉耀,可以把迭代器理解成一個帶有流水線的工程,我們每次詢問他時蹋偏,他就給我們返回下一個值便斥。迭代器會把所有的值都存儲在內(nèi)存中。

2.1 next()

next()函數(shù) 用來返回文件的下一行/下一個值威始,直到促發(fā)STopIteration枢纠。
《Python File next() 方法》

2.2 iter()

用處:把可迭代對象變?yōu)榈鳌?/p>

3 可迭代對象(iterable)


凡是可以返回一個迭代器的對象都可以稱之為可迭代對象(除了上面提到的list,tuples,dict等容器外,還有很多其他對象也是可迭代對象黎棠。比如晋渺,打開狀態(tài)的files.
我的理解是所有可以使用 for .. in .. 語法的對象都可以叫做一個迭代對象。
但是迭代器把所有的值都存儲到了內(nèi)存中脓斩,如果有大量數(shù)據(jù)的話木西,這個方式就會占用大量內(nèi)存。

注:很多容器都是可迭代對象随静,但并不是所有容器都是可迭代對象.

下面的例子可以幫助更好的理解可迭代對象八千。

 >>> x = [1, 2, 3]
>>> y = iter(x)
>>> z = iter(x)
>>> next(y)
1
>>> next(y)
2
>>> next(z)
1
>>> type(x)
<class 'list'>
>>> type(y)
<class 'list_iterator> 

上題中,x就是一個可迭代對象燎猛×道Γ可迭代對象和容器一樣是一種通俗的叫法,并不是指某種具體的數(shù)據(jù)類型扛门,列表是可迭代對象鸠信,字典是可迭代對象,集合也是可迭代對象论寨。

我們用 liter() 函數(shù)可以把可迭代對象變?yōu)榈鲗ο蟆?/p>

上面代碼中星立,y和z是兩個獨立的迭代器爽茴。迭代器內(nèi)部持有一個狀態(tài),該狀態(tài)用于記錄當前迭代所在的位置绰垂,以方便下次迭代的時候獲取正確的元素室奏。迭代器有一種具體的迭代器類型,比如list_iterator劲装,set_iterator胧沫。可迭代對象實現(xiàn)了iter方法占业,該方法返回一個迭代器對象绒怨。
當運行以下代碼時:

x = [1, 2, 3]
for elemments in x:
    ...

實際執(zhí)行情況是:

迭代對象--->迭代器

4 生成器(generator)


生成器其實是一種特殊的迭代器。它和一般迭代器不同的地方在于谦疾,我們 只可以讀取它一次南蹂,因為它并不把所有的值放在內(nèi)存中,它是實時地生成數(shù)據(jù):

>>> mygenerator = (x*x for x in range(3))  #range后面會介紹
>>> for i in mygenerator :
...    print(i)

結(jié)果:
0
1
4

生成器只能讀取一次是什么意思念恍?舉個例子:

# -*- coding: UTF-8 -*-
def mygenerator(n):   #建一個生成器
     for x in range(n):
         yield int(x)


y = mygenerator(5) 
z = sum(y) # 使用一次生成器六剥。遍歷mygenerator中所有數(shù),并相加

for i in y:    #第二次使用生成器
    print(i)   #print不會有任何結(jié)果峰伙,因為已經(jīng)使用過一次生成器疗疟。

本節(jié)中其他相關(guān)函數(shù)的意思:

range()
range(y,x,z); y表示起始范圍,x表示終止范圍瞳氓,z表示間隔值
1.range(x) 表示0-x范圍內(nèi)的數(shù)(不包含x)
2.range(y,x)表示y-x范圍內(nèi)的數(shù)(不包含x)
3.range(y,x,z)表示y-x范圍內(nèi)(不包含x),間隔為z的數(shù).

更具體一點的說明:
《詳細記錄python的range()函數(shù)用法》

和range()函數(shù)相似的策彤,還有個xrange()函數(shù),具體見下面說明:

xrange()
參數(shù)與range()函數(shù)一樣顿膨,不一樣的地方在于锅锨,xrange()生成的不是一個數(shù)組,而是一個生成器恋沃。

xrange() 和 range()的區(qū)別可以參見以下詳細資料:
《Python的range和xrange》

舉例:

>>> range(5) 
[0, 1, 2, 3, 4] 
>>> xrange(5)
xrange(5)
>>> list(xrange(5))
[0, 1, 2, 3, 4]

由上面可以必搞,range()會直接生成列表,而xrange()會生成一個生成器囊咏。因此恕洲,range相比于xrange會預先占用很多資源。

比如梅割,如果是range(1000)霜第,那個range會直接生成0-1000的列表,預先占用內(nèi)存户辞;但是xrange只會生成xrange生成器泌类,需要用到具體函數(shù)時,再占用相應的內(nèi)存底燎。所以xrange做循環(huán)的性能比range好刃榨,尤其是返回很大的時候弹砚,盡量用xrange。

生成器與迭代器的代碼區(qū)分

例子:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist :
...    print(i)

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator :
...    print(i)

前一個[ ] 迭代器枢希,后一個()生成器桌吃。

5 yield 關(guān)鍵詞


yield 是一個類似 return 的關(guān)鍵字,只是這個函數(shù)返回的是個生成器苞轿。

>>> def createGenerator() :
...    mylist = range(3)
...    for i in mylist :
...        yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

當我們用print(mygenerator)調(diào)用createGenerator()這個函數(shù)的時候茅诱,函數(shù)內(nèi)部的代碼并不立馬執(zhí)行 ,這個函數(shù)只是返回一個生成器對象搬卒。

只有當我們使用for進行迭代的時候瑟俭,函數(shù)內(nèi)代碼才會執(zhí)行。

第一次迭代時,函數(shù)從開始一直執(zhí)行到 yield這個 關(guān)鍵字秀睛,然后返回 yield 后的值(即ii)作為第一次迭代的返回值(即將0作為返回值).每次執(zhí)行這個函數(shù)尔当,都會繼續(xù)執(zhí)行你在函數(shù)內(nèi)部定義的那個循環(huán)的下一次,再返回那個值蹂安。例如,第二次執(zhí)行锐帜,迭代返回值為11=1田盈。當我們不斷調(diào)用,這個過程會一直持續(xù)缴阎,直到?jīng)]有可以返回的值為止允瞧。
生成器下一次迭代是從上一次結(jié)束的地方開始,而不會從頭開始蛮拔。比如第一次迭代后述暂。第二次迭代是從i=1開始,而不是從i=0開始建炫。

如果生成器內(nèi)部沒有定義 yield 關(guān)鍵字畦韭,那么這個生成器被認為成空的。這種情況可能因為是循環(huán)進行沒了肛跌,或者是沒有滿足 if/else 條件艺配。

迭代器有關(guān)工具:itertools

itertools 是一個模塊,集合了眾多的迭代函數(shù)衍慎,功能非常強大转唉,具體可以見以下內(nèi)容

《PYTHON-進階-ITERTOOLS模塊小結(jié)》


參考資料

1《(譯)Python關(guān)鍵字yield的解釋》
2.《完全理解 Python 迭代對象、迭代器稳捆、生成器》
3.知乎:《如何更好地理解Python迭代器和生成器赠法?》
4《PYTHON-進階-ITERTOOLS模塊小結(jié)》
5《Python的range和xrange》
6《詳細記錄python的range()函數(shù)用法》
7《Python File next() 方法》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乔夯,一起剝皮案震驚了整個濱河市砖织,隨后出現(xiàn)的幾起案子款侵,更是在濱河造成了極大的恐慌,老刑警劉巖镶苞,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喳坠,死亡現(xiàn)場離奇詭異,居然都是意外死亡茂蚓,警方通過查閱死者的電腦和手機壕鹉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聋涨,“玉大人晾浴,你說我怎么就攤上這事‰拱祝” “怎么了脊凰?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茂腥。 經(jīng)常有香客問我狸涌,道長,這世上最難降的妖魔是什么最岗? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任帕胆,我火速辦了婚禮,結(jié)果婚禮上般渡,老公的妹妹穿的比我還像新娘懒豹。我一直安慰自己,他們只是感情好驯用,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布脸秽。 她就那樣靜靜地躺著,像睡著了一般蝴乔。 火紅的嫁衣襯著肌膚如雪记餐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天淘这,我揣著相機與錄音剥扣,去河邊找鬼。 笑死铝穷,一個胖子當著我的面吹牛钠怯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曙聂,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼晦炊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起断国,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤贤姆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后稳衬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霞捡,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年薄疚,在試婚紗的時候發(fā)現(xiàn)自己被綠了碧信。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡街夭,死狀恐怖砰碴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情板丽,我是刑警寧澤呈枉,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站埃碱,受9級特大地震影響猖辫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砚殿,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一住册、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓮具,春花似錦、人聲如沸凡人。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挠轴。三九已至传睹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間岸晦,已是汗流浹背欧啤。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留启上,地道東北人邢隧。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像冈在,于是被迫代替她去往敵國和親倒慧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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