5.1 Iterable
和 Iterator
如你已經知道的,迭代器是實現迭代器協定的對象,允許 逐個獲取集合中的元素。 在 Python 中,迭代器被廣泛用於遍歷像列表、元組和字符串這樣的序列的元素。
來看看迭代器是如何工作的以及如何使用它們。
可迭代對象 (Iterable)
要能通過 for
迴圈遍歷對象,它必須是可迭代的 – Iterable
。這意味著,我們的對象必須
實現 方法 __iter__()
,
該方法返回一個迭代器對象。
迭代器對象 (Iterator)
這是一個特殊的對象,它有一個
函數 __next__()
用於返回
序列中的下一個元素。當元素
結束時,方法 __next__()
會拋出異常
StopIteration
作為迭代結束的標誌。
迭代器還必須實現方法 __iter__()
,
它返回該迭代器自身。
使用 Python 內建函數的示例
在這個例子中,列表
numbers 是一個可迭代對象。我們通過函數
iter()
獲取迭代器,並使用函數
next()
來遍歷元素,直到拋出
StopIteration
異常。
# 可迭代對象
numbers = [1, 2, 3, 4, 5]
# 從可迭代對象獲取迭代器
iterator = iter(numbers)
# 使用迭代器來遍歷元素
try:
while True:
number = next(iterator)
print(number)
except StopIteration:
pass
這正是當你寫類似的代碼時所發生的事情:
# 可迭代對象
numbers = [1, 2, 3, 4, 5]
for number in numbers:
print(number)
5.2 迭代器的本質
迭代器是一種對象,它幫助我們逐個遍歷一組元素。它的實現可以是多種多樣的。我們來編寫自己的類,實現迭代器的所有要求。
步驟 1. 首先創建自己的類
讓它逐個返回從 start
到
end
的數字
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
步驟 2. 支援函數 __iter__
現在我們需要給它添加一個函數 __iter__
,
該函數將返回能調用 __next()__
函數的迭代器對象。我們將返回自己的對象引用 – 這是允許的。
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
步驟 3. 支援函數 __next__
現在需要給我們的迭代器對象添加函數 __next__
,該函數將返回我們列表的下一個元素。我們將只使用變數 current
:
def __next__(self):
current = self.current
self.current += 1
return current
步驟 4. 停止迭代器
如果迭代器已經返回了所有計劃返回的值,則應該引發異常 StopIteration
。讓我們稍微修改最後一個函數:
def __next__(self):
if self.current >= self.end:
raise StopIteration
current = self.current
self.current += 1
return current
太好了。現在可以使用我們的迭代器。以下是我們所有代碼的示例:
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.current >= self.end:
raise StopIteration
current = self.current
self.current += 1
return current
# 創建自定義迭代器的實例
my_iter = MyIterator(1, 5)
# 使用迭代器來遍歷元素
for num in my_iter:
print(num)
5.3 正確的迭代器
上一個例子的迭代器有什麼不好?是的,這是個迭代器,它能運行,但它太過原始。無法同時用不同的迭代器遍歷同一集合的元素。
更正確的做法是編寫一些代碼,在 __iter__
方法中返回一個獨立的對象,
該對象能正確地返回所有元素。
例子:
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
return MyIterator(self.data)
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
item = self.data[self.index]
self.index += 1
return item
# 使用
my_iterable = MyIterable([1, 2, 3, 4])
for item in my_iterable:
print(item)
在這個例子中,我們有兩個類 — 第一個類傳遞要用迭代器遍歷的集合。第二個類是迭代器,它在 next()
方法中返回集合的元素。這個也很簡單,但這樣才是將迭代器添加到你的類中的正確方式。
GO TO FULL VERSION