Python 簡易自建迭代器
分類
建立時間: 2023年1月9日 20:54
更新時間: 2023年1月10日 03:15
說明
大家都知道 for 迴圈,相信也很常看到下列這段程式
for i in range(5):
print(i)
輸出
0
1
2
3
4
這次要分享如何實作類似 range()
的物件
基本的迭代器
A.py
class A:
def __init__(self):
self.x = 0
def __iter__(self):
return self
def __next__(self):
if self.x > 2:
raise StopIteration
else:
self.x += 1
return self.x
__init__()
: 這個是比較常見的初始化,像是建構子那樣__iter__()
: 回傳可迭代的物件,這邊讓它回傳自己__next__()
: 就像是每一次迭代條件式和運算式(例如常見的 i++)- StopIteration: 代表迴圈結束
最後使用 for 迴圈跑 A 類別結果如下
for i in A():
print(i)
輸出
1
2
3
非同步迭代器
在《Python 非同步設計使用 Asyncio》書中,他有舉例一個使用 redis 的非同迭代器,為了方便執行,我拿掉 redis 連線等一系列的動作改成 sleep 來模擬非同步迭代器
OneAtATime.py
import asyncio
class OneAtATime:
def __init__(self, keys):
self.keys = keys
def __aiter__(self):
self.ikeys = iter(self.keys)
return self
async def __anext__(self):
try:
key = next(self.ikeys)
except StopIteration:
raise StopAsyncIteration
await asyncio.sleep(1)
return key
__aiter__
: 與__iter__()
一樣,但是它是用於非同步迭代器__anext__()
: 與__next__()
一樣,但是它是用於非同步迭代器iter()
: 用來存放迭代的 keynext()
: 取得iter()
存放的 key- StopAsyncIteration: 用來通知非同步迭代器已結束,可以看到上面先捕捉 StopIteration,再拋出 StopAsyncIteration
- 需注意
def __aiter__()
沒有加 async,而async def __anext__()
有加 async
使用範例
import asyncio
async def main():
await asyncio.sleep(1)
keys = ['1', '2', '3', '4', '5',]
async for value in OneAtATime(keys):
print(value)
asyncio.run(main())
輸出
1
2
3
4
5
非同步程式我自己還在學習當中,還不太清楚該如何活用,上面這個例子只能用來分享有非同步迭代器這個東西,在《Python 非同步設計使用 Asyncio》書中,作者有提到更簡單的寫法,但這並非迭代器的議題,以後有機會我再分享非同步程式設計給大家。
觀看次數: 581
__iter____next__foriniteratorpython迭代器
一杯咖啡的力量,勝過千言萬語的感謝。
支持我一杯咖啡,讓我繼續創作優質內容,與您分享更多知識與樂趣!