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