迭代器

一、可迭代對象和迭代器

1.迭代的概念

上一次輸出的結(jié)果為下一次輸入的初始值,重復(fù)的過程稱為迭代,每次重復(fù)即一次迭代末贾,并且每次迭代的結(jié)果是下一次迭代的初始值

注:循環(huán)不是迭代

while True: #只滿足重復(fù)蜓洪,因而不是迭代

print('====>')

2.可迭代的對象

內(nèi)置__iter__方法的皮服,都是可迭代的對象。

list是可迭代對象着饥,dict是可迭代對象犀农,set也是可迭代對象。

[1,2].__iter__()

'hello'.__iter__()

(1,2).__iter__()

{'a':1,'b':2}.__iter__()

{1,2,3}.__iter__()

例如:

x = [1, 2, 3]

y = iter(x)

z = iter(x)

print(next(y))

print(next(y))

print(next(z))

print(type(x))

print(type(y))

輸出

1

2

1

;

3.迭代器

·1.為什么要有迭代器宰掉?

對于沒有索引的數(shù)據(jù)類型呵哨,必須提供一種不依賴索引的迭代方式赁濒。

·2.迭代器定義:

迭代器:可迭代對象執(zhí)行__iter__方法,得到的結(jié)果就是迭代器孟害,迭代器對象有__next__方法

它是一個帶狀態(tài)的對象拒炎,他能在你調(diào)用next()方法的時候返回容器中的下一個值,任何實現(xiàn)了__iter__和__next__()方法的對象都是迭代器纹坐,__iter__返回迭代器自身枝冀,__next__返回容器中的下一個值,如果容器中沒有更多元素了耘子,則拋出StopIteration異常

·3.迭代器的實現(xiàn)

例:

i=[1,2,3].__iter__()

print(i)    #迭代器

print(i.__next__())

print(i.__next__())

print(i.__next__())

#print(i.__next__()) #拋出異常:StopIteration

輸出

1

2

3

每次調(diào)用next()方法的時候做兩件事:

00001.為下一次調(diào)用next()方法修改狀態(tài)

00002.為當(dāng)前這次調(diào)用生成返回結(jié)果

迭代器就像一個懶加載的工廠果漾,等到有人需要的時候才給它生成值返回,沒調(diào)用的時候就處于休眠狀態(tài)等待下一次調(diào)用谷誓。

·4.如何判斷迭代器對象和可迭代對象

from collections importIterable,Iterator

'abc'.__iter__()

().__iter__()

[].__iter__()

{'a':1}.__iter__()

{1,2}.__iter__()

f=open('a.txt','w')

f.__iter__()

#判斷是否為可迭代對象绒障,以下都是

print(isinstance('abc',Iterable))

print(isinstance([],Iterable))

print(isinstance((),Iterable))

print(isinstance({'a':1},Iterable))

print(isinstance({1,2},Iterable))

print(isinstance(f,Iterable))

#判斷是否為迭代器,只有文件是

print(isinstance('abc',Iterator))

print(isinstance([],Iterator))

print(isinstance((),Iterator))

print(isinstance({'a':1},Iterator))

print(isinstance({1,2},Iterator))

print(isinstance(f,Iterator))

輸出

True

True

True

True

True

True

False

False

False

False

False

True

可迭代對象:只有__iter__方法捍歪,執(zhí)行該方法得到的迭代器對象

迭代器:有__iter__和__next__()方法

注:對于迭代器對象來說户辱,執(zhí)行__iter__方法,得到的結(jié)果仍然是它本身

·5.迭代器的優(yōu)點和缺點

優(yōu)點:

1.提供了一種不依賴下標的迭代方式

2.就跌迭代器本身來說糙臼,更節(jié)省內(nèi)存

缺點:

1. 無法獲取迭代器對象的長度

2. 不如序列類型取值靈活庐镐,是一次性的,只能往后取值变逃,不能往前退

二必逆、生成器

1.定義

生成器(generator)是一個特殊的迭代器,它的實現(xiàn)更簡單優(yōu)雅揽乱,yield是生成器實現(xiàn)__next__()方法的關(guān)鍵名眉。它作為生成器執(zhí)行的暫停恢復(fù)點凰棉,可以對yield表達式進行賦值损拢,也可以將yield表達式的值返回。

也就是說撒犀,yield是一個語法糖福压,內(nèi)部實現(xiàn)支持了迭代器協(xié)議,同時yield內(nèi)部是一個狀態(tài)機或舞,維護著掛起和繼續(xù)的狀態(tài)隧膏。

yield的功能:

1.相當(dāng)于為函數(shù)封裝好__iter__和__next__

2.return只能返回一次值,函數(shù)就終止了嚷那,而yield能返回多次值胞枕,每次返回都會將函數(shù)暫停,下一次next會從上一次暫停的位置繼續(xù)執(zhí)行

例:

defcounter(n):

print('start...')

i=0

while i < n:

yield i

i+=1

print('end...')

g=counter(5)

print(g)

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

# print(next(g)) ??#會報錯

輸出

start...

0

1

2

3

4

2.生成器函數(shù)

·生成器函數(shù):常規(guī)函數(shù)定義魏宽,但是腐泻,使用yield語句而不是return語句返回結(jié)果决乎。yield語句一次返回一個結(jié)果,在每個結(jié)果中間派桩,掛起函數(shù)的狀態(tài)构诚,以便下次重它離開的地方繼續(xù)執(zhí)行擦耀;

普通函數(shù)return返回

deflay_eggs(num):

egg_list=[]

for egg in range(num):

egg_list.append('蛋%s' %egg)

return egg_list

yikuangdan=lay_eggs(10) #我們拿到的是蛋

print(yikuangdan)

輸出

['蛋0', '蛋1', '蛋2', '蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']

迭代器函數(shù)

deflay_eggs(num):

for egg in range(num):

res='蛋%s' %egg

yield res ??????#生成器關(guān)鍵語法

print('下完一個蛋')

laomuji=lay_eggs(10) #我們拿到的是一只母雞

print(laomuji)

print(laomuji.__next__()) ??????#迭代 ?蛋0

print(laomuji.__next__()) ????#蛋1

print(laomuji.__next__()) ??????#蛋2

egg_l=list(laomuji)

print(egg_l)

輸出

蛋0

下完一個蛋

蛋1

下完一個蛋

蛋2

下完一個蛋

下完一個蛋

下完一個蛋

下完一個蛋

下完一個蛋

下完一個蛋

下完一個蛋

下完一個蛋

['蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']

3.生成器表達式

·生成器表達式:類似于列表推導(dǎo)拆挥,但是,生成器返回按需產(chǎn)生結(jié)果的一個對象普碎,而不是一次構(gòu)建一個結(jié)果列表员魏;

·

food=yield food_list

·

#g.send('food1'),先把food1傳給yield丑蛤,由yield賦值給food,然后返回給food_list,然后再往下執(zhí)行撕阎,直到再次碰到y(tǒng)ield受裹,然后把yield后的返回值返回給food_list

·

注意:開始生成器不能send非空值

def eater(name): ???????#協(xié)程函數(shù)

print('%s ready to eat' %name)

food_list=[]

while True:

food=yield food_list ??????????#裝飾器表達式 ???????food_list.append(food)

print('%s start to eat %s' %(name,food))

g=eater('hexin')

print(g) ???????#生成器

print(g.send('food1')) ?#傳值

輸出

Traceback (most recent call last):

    #生成器對象

File "/Users/hexin/PycharmProjects/py3/day5/2.py", line 71, in

print(g.send('food1'))

TypeError: can't send non-None value to a just-started generator    #開始生成器不能send非空值

·初始化后

def eater(name): ???????#協(xié)程函數(shù)

print('%s ready to eat' %name)

food_list=[]

while True:

food=yield food_list ??????????#裝飾器表達式 ???????food_list.append(food)

print('%s start to eat %s' %(name,food))

g=eater('hexin')

print(g) ???????#生成器

next(g) #等同于 g.send(None),初始化

print(g.send('food1'))

輸出

hexin ready to eat

hexin start to eat food1

['food1']

·為了防止忘記初始化虏束,可利用裝飾器進行初始化棉饶,如下

def deco(func): ????#初始化函數(shù)

def wrapper(*args,**kwargs):

res=func(*args,**kwargs)

next(res) ?????????#等同于 g.send(None),初始化

return res

return wrapper

@deco ??????#用初始化函數(shù)裝飾器,調(diào)用初始化函數(shù)

def eater(name): ???????#協(xié)程函數(shù)

print('%s ready to eat' %name)

food_list=[]

while True:

food=yield food_list ??????????#裝飾器表達式 ???????food_list.append(food)

print('%s start to eat %s' %(name,food))

g=eater('hexin')

# print(g) ???????#生成器

# next(g) #等同于 g.send(None)镇匀,初始化

print(g.send('food1'))

print(g.send('food2'))

print(g.send('food3'))

輸出

hexin ready to eat

hexin start to eat food1

['food1']

hexin start to eat food2

['food1', 'food2']

hexin start to eat food3

['food1', 'food2', 'food3']

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末照藻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子汗侵,更是在濱河造成了極大的恐慌幸缕,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晃择,死亡現(xiàn)場離奇詭異冀值,居然都是意外死亡也物,警方通過查閱死者的電腦和手機宫屠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滑蚯,“玉大人浪蹂,你說我怎么就攤上這事「娌模” “怎么了坤次?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斥赋。 經(jīng)常有香客問我缰猴,道長,這世上最難降的妖魔是什么疤剑? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任滑绒,我火速辦了婚禮闷堡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疑故。我一直安慰自己杠览,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布纵势。 她就那樣靜靜地躺著踱阿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钦铁。 梳的紋絲不亂的頭發(fā)上软舌,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音育瓜,去河邊找鬼葫隙。 笑死,一個胖子當(dāng)著我的面吹牛躏仇,可吹牛的內(nèi)容都是我干的恋脚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼焰手,長吁一口氣:“原來是場噩夢啊……” “哼糟描!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起书妻,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤船响,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后躲履,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體见间,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年工猜,在試婚紗的時候發(fā)現(xiàn)自己被綠了米诉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡篷帅,死狀恐怖史侣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情魏身,我是刑警寧澤惊橱,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站箭昵,受9級特大地震影響税朴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一正林、第九天 我趴在偏房一處隱蔽的房頂上張望茧跋。 院中可真熱鬧,春花似錦卓囚、人聲如沸瘾杭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粥烁。三九已至,卻和暖如春蝇棉,著一層夾襖步出監(jiān)牢的瞬間讨阻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工篡殷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钝吮,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓板辽,卻偏偏與公主長得像奇瘦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子劲弦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

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