您好,登錄后才能下訂單哦!
這篇文章主要介紹了python如何自定義迭代器,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
對于新的和經(jīng)驗豐富的 Python 開發(fā)者來說,自定義迭代器是一個非常強大的但令人迷惑的主題。
許多內(nèi)置類型,例如列表、集合和字典,已經(jīng)實現(xiàn)了允許它們在底層迭代的協(xié)議。這使我們可以輕松地遍歷它們。
>>> for food in ['Pizza', 'Fries']: print(food + '. Yum!') Pizza. Yum!Fries. Yum!
我們?nèi)绾蔚覀冏约旱淖远x類?首先,讓我們來澄清一些術(shù)語。
要成為一個可迭代對象,一個類需要實現(xiàn) __iter__()
__iter__()
方法需要返回一個迭代器
要成為一個迭代器,一個類需要實現(xiàn) __next__()
(或在 Python 2中是 next()
),當(dāng)沒有更多的項要迭代時,必須拋出一個 StopIteration
異常。
呼!這聽起來很復(fù)雜,但是一旦你記住了這些基本概念,你就可以在任何時候進(jìn)行迭代。
我們什么時候想使用自定義迭代器?讓我們想象一個場景,我們有一個 Server
實例在不同的端口上運行不同的服務(wù),如 http
和 ssh
。其中一些服務(wù)處于 active
狀態(tài),而其他服務(wù)則處于 inactive
狀態(tài)。
class Server: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 80}, ]
當(dāng)我們遍歷 Server
實例時,我們只想遍歷那些處于 active
的服務(wù)。讓我們創(chuàng)建一個 IterableServer
類:
class IterableServer: def __init__(self): self.current_pos = 0 def __next__(self): pass # TODO: 實現(xiàn)并記得拋出 StopIteration
首先,我們將當(dāng)前位置初始化為 0
。然后,我們定義一個 __next__()
方法來返回下一項。我們還將確保在沒有更多項返回時拋出 StopIteration
。到目前為止都很好!現(xiàn)在,讓我們實現(xiàn)這個 __next__()
方法。
class IterableServer: def __init__(self): self.current_pos = 0. # 我們初始化當(dāng)前位置為 0 def __iter__(self): # 我們可以在這里返回 self,因為實現(xiàn)了 __next__ return self def __next__(self): while self.current_pos < len(self.services): service = self.services[self.current_pos] self.current_pos += 1 if service['active']: return service['protocol'], service['port'] raise StopIteration next = __next__ # 可選的 Python2 兼容性
我們對列表中的服務(wù)進(jìn)行遍歷,而當(dāng)前的位置小于服務(wù)的個數(shù),但只有在服務(wù)處于活動狀態(tài)時才返回。一旦我們遍歷完服務(wù),就會拋出一個 StopIteration
異常。
因為我們實現(xiàn)了 __next__()
方法,當(dāng)它耗盡時,它會拋出 StopIteration
。我們可以從 __iter__()
返回 self
,因為 IterableServer
類遵循 iterable
協(xié)議。
現(xiàn)在我們可以遍歷一個 IterableServer
實例,這將允許我們查看每個處于活動的服務(wù),如下所示:
>>> for protocol, port in IterableServer(): print('service %s is running on port %d' % (protocol, port)) service ssh is running on port 22 service http is running on port 21
太棒了,但我們可以做得更好!在這樣類似的實例中,我們的迭代器不需要維護(hù)大量的狀態(tài),我們可以簡化代碼并使用 generator(生成器) 來代替。
class Server: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 21}, ] def __iter__(self): for service in self.services: if service['active']: yield service['protocol'], service['port']
yield
關(guān)鍵字到底是什么?在定義生成器函數(shù)時使用 yield。這有點像 return
,雖然 return
在返回值后退出函數(shù),但 yield
會暫停執(zhí)行直到下次調(diào)用它。這允許你的生成器的功能在它恢復(fù)之前保持狀態(tài)。查看 yield 的文檔以了解更多信息。使用生成器,我們不必通過記住我們的位置來手動維護(hù)狀態(tài)。生成器只知道兩件事:它現(xiàn)在需要做什么以及計算下一個項目需要做什么。一旦我們到達(dá)執(zhí)行點,即 yield
不再被調(diào)用,我們就知道停止迭代。
這是因為一些內(nèi)置的 Python 魔法。在 Python 關(guān)于 __iter__()
的文檔中我們可以看到,如果 __iter__()
是作為一個生成器實現(xiàn)的,它將自動返回一個迭代器對象,該對象提供 __iter__()
和 __next__()
方法。閱讀這篇很棒的文章,深入了解迭代器,可迭代對象和生成器。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“python如何自定義迭代器”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。