摘要:滿足以上要求的對象,就是迭代器。其中,必需返回一個迭代器對象,則負(fù)責(zé)迭代邏輯并在迭代完畢時觸發(fā)異常。可以在遍歷迭代器的時候,加入一個判斷語句,避免無法多次迭代的情況發(fā)生參考資料官網(wǎng)迭代器文檔
什么是迭代器 相關(guān)概念定義 迭代器(Iterator):
滿足迭代協(xié)議的對象就是迭代器
iterator就是實(shí)現(xiàn)了Iteration Protocol的對象,這類對象都支持循環(huán)遍歷的操作(for/while/支持迭代的函數(shù)list() sum()...)。
內(nèi)建函數(shù)iter()接收一個可迭代對象,并返回一個可迭代對象.
每次將這個可迭代對象傳遞給next()函數(shù),都會返回它所包含的下一個元素,當(dāng)?shù)曜詈笠粋€元素時,就會觸發(fā)StopIteration異常。
>>> x = iter([1, 2, 3]) >>> x>>> next(x) 1 >>> next(x) 2 >>> next(x) 3 >>> next(x) Traceback (most recent call last): File " ", line 1, in StopIteration
滿足以上要求的對象,就是迭代器。
迭代隱含的操作在每次的迭代語句中,python都會按照迭代協(xié)議去對迭代器進(jìn)行迭代。其實(shí),在實(shí)際執(zhí)行中,python會進(jìn)行一些其他的操作:
將需要迭代的對象作為參數(shù)傳遞給iter函數(shù)
iter返回一個迭代器對象
每次循環(huán)則將返回的迭代器對象傳遞給next函數(shù)
循環(huán)至最后一個元素,觸發(fā)StopIteration
以for語句為例:
當(dāng)我們在Python中執(zhí)行循環(huán)語句for i in foo的時候,其背后的操作是:
foo = iter(foo)
next(foo)
next(foo)在python3中執(zhí)行的是:foo.__next__(),在python2中則是:foo.next()
迭代器的實(shí)現(xiàn)迭代器是用class來實(shí)現(xiàn)的。其中必需實(shí)現(xiàn)的有兩個方法:__iter__、next(python2)/__next__(python3)。其中,__iter__必需返回一個迭代器對象,next則負(fù)責(zé)迭代邏輯并在迭代完畢時觸發(fā)異常。
如下:
def Iter(object) def __init__(self): pass def __iter__(self): pass def __next__(self): # python3 pass def next(self): # python2 pass
迭代器的__iter__方法需要返回的是一個具有next方法的可迭代對象。如果當(dāng)__iter__返回的是self的話,就會產(chǎn)生其他意想不到的效果。
class yrange: def __init__(self, n): self.i = 0 self.n = n def __iter__(self): return self def next(self): if self.i < self.n: i = self.i self.i += 1 return i else: raise StopIteration() class zrange: def __init__(self, n): self.i = 0 self.n = n def __iter__(self): return zrange(self.n) def next(self): if self.i < self.n: i = self.i self.i += 1 return i else: raise StopIteration()
執(zhí)行結(jié)果:
>>> y = yrange(5) >>> list(y) [0, 1, 2, 3, 4] >>> list(y) [] >>> z = zrange(5) >>> list(z) [0, 1, 2, 3, 4] >>> list(z) [0, 1, 2, 3, 4]
在yrange中,iter返回的是self,在執(zhí)行list(y)時iter返回的都是同一個self,所以再次調(diào)用list(y)時只會觸發(fā)結(jié)束迭代異常,列表中并無內(nèi)容。
而在zrange中,每次執(zhí)行list(z)時,iter都是返回一個新的迭代器zrange(self.n),所以每次執(zhí)行list(z)都得到完整的元素。
通常,對于數(shù)據(jù)量特別大的序列,我們會用生成器generator來代替容器對象container,這樣可以利用lazy evaluable來節(jié)省內(nèi)存開銷。值得注意的是,生成器也是一個只能迭代一次的迭代器。
def grange(n): i = 0 while i < n: yield i i += 1
執(zhí)行結(jié)果:
>>> glist = grange(10) >>> list(glist) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(glist) []
如果是利用便捷的生成器表達(dá)式也是一樣:
>>> alist = (i for i in range(10)) >>> list(alist) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(alist) []
要解決這個問題,可以將迭代器和生成器組合使用:
class Grange(object): def __init__(self, n): self.n = n def __iter__(self): for i in range(self.n): yield i
結(jié)果:
>>> glist = Grange(10) >>> list(glist) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(glist) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
值得注意的是,平常我們利用到生成器的地方都是數(shù)據(jù)量特別大的情況,這個時候,其實(shí)應(yīng)該盡量避免多次迭代生成器。我想這應(yīng)該也是python沒有支持對生成器多次迭代的特性的原因。
編程建議在實(shí)際的編程中,往往需要在函數(shù)中多次迭代一個序列,如果這個序列是調(diào)用API得到的,而你又不能保證它是沒有陷阱的迭代器時。可以在遍歷迭代器的時候,加入一個判斷語句,避免無法多次迭代的情況發(fā)生:
def iterator_checker(iterator): assert iter(iterator) is not iter(iterator), "iter() return self"參考資料
python官網(wǎng)迭代器文檔
python practice book
<
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/38062.html
摘要:迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結(jié)束。迭代器有兩個基本的方法和。調(diào)用一個生成器函數(shù),返回的是一個迭代器對象。生成器函數(shù)生成器函數(shù)返回一個迭代器函數(shù)函數(shù)傳入不定長參數(shù)加了星號的變量名會存放所有未命名的變量參數(shù)。 Python學(xué)習(xí)--最完整的基礎(chǔ)知識大全 關(guān)于python的基礎(chǔ)知識學(xué)習(xí),網(wǎng)上有很多資料,今天我就把我收藏的整理一下分享給大家! 菜鳥教程pytho...
摘要:迭代器模式原文地址更多設(shè)計模式系列教程更多免費(fèi)教程博主按每天一個設(shè)計模式旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實(shí)現(xiàn)。迭代器模式常見和常用的有內(nèi)部迭代器外部迭代器倒序迭代器等等。 迭代器模式·原文地址 更多《設(shè)計模式系列教程》 更多免費(fèi)教程 博主按:《每天一個設(shè)計模式》旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用javascript(靠這吃飯)和python(純粹喜歡...
摘要:迭代器模式原文地址更多設(shè)計模式系列教程更多免費(fèi)教程博主按每天一個設(shè)計模式旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實(shí)現(xiàn)。迭代器模式常見和常用的有內(nèi)部迭代器外部迭代器倒序迭代器等等。 迭代器模式·原文地址 更多《設(shè)計模式系列教程》 更多免費(fèi)教程 博主按:《每天一個設(shè)計模式》旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用javascript(靠這吃飯)和python(純粹喜歡...
摘要:時間永遠(yuǎn)都過得那么快,一晃從年注冊,到現(xiàn)在已經(jīng)過去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時候把他們整理一下了。那是因?yàn)槭詹貖A太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...
摘要:勤學(xué)學(xué)習(xí)效率與效果取決于執(zhí)行力。這一步學(xué)習(xí)的正確姿勢是在實(shí)踐操作中發(fā)掘問題,然后帶著問題找答案。拆分任務(wù)將目標(biāo)分解成具體可執(zhí)行的學(xué)習(xí)任務(wù)。勤學(xué)強(qiáng)大的執(zhí)行力是學(xué)習(xí)的根本保障。分享復(fù)述檢驗(yàn)學(xué)習(xí)成果,提高學(xué)習(xí)效果的最好方法。 showImg(https://segmentfault.com/img/bVbcPGZ?w=256&h=256); 前段時間和大家一起分享了一篇關(guān)于學(xué)習(xí)方法內(nèi)容《大牛...
閱讀 2073·2021-11-24 09:39
閱讀 788·2021-09-30 09:48
閱讀 980·2021-09-22 15:29
閱讀 2415·2019-08-30 14:17
閱讀 1891·2019-08-30 13:50
閱讀 1343·2019-08-30 13:47
閱讀 982·2019-08-30 13:19
閱讀 3423·2019-08-29 16:43