Python學習之迭代器協議

ARM的程式設計師敲著詩歌的夢發表於2020-04-04

迭代(iteration)

逐個獲取元素的過程,就是「迭代」。

例如:

# iteration
# 用 for 迴圈迭代序列
a_list = [1, 2, 3]
for i in a_list:
    print(i)

可迭代(iterable)

實現了方法 __iter__ 的物件是可迭代的。

如果你暫時聽不懂,那可以簡單地理解為:如果我們可以從一個物件中逐個地獲取元素,那麼我們就說這個物件是「可迭代」的。

Python 中的順序型別,都是可迭代的,例如 listtuple,、string;另外 dictsetfile 也是可迭代的。

迭代器(iterator)

實現了方法 __next__ 的物件是迭代器。

當你呼叫方法 __next__ (可不提供任何引數)時,迭代器應返回下一個值。如果迭代器沒有可供返回的值,應引發 StopIteration 異常。

你還可使用內建的便利函式 next,在這種情況下,next(it)it.__next__() 等效。

迭代器協議(iterator protocol)

迭代器協議指的是容器類需要包含一個特殊方法,這個特殊方法就是 __iter__() 方法。

如果一個容器類提供了 __iter__() 方法,並且該方法能返回一個能夠逐個訪問容器內所有元素的迭代器,則我們說該容器類實現了迭代器協議。

迭代器協議與 for 迴圈

講這個例子,是為了更好地理解迭代器協議。

# iterator protocol and for loop
for x in something:
    print(x)

Python 處理 for 迴圈時,首先會呼叫 something.__iter__(),返回 something 對應的迭代器(假設叫 it);而後,for 迴圈會呼叫 it.__next__(),獲取迭代器的下一個元素,並賦值給 x,然後執行迴圈體;執行完後,for 迴圈會繼續呼叫 it.__next__(),獲取迭代器的下一個元素,並賦值給 x,執行迴圈體 …… 當 for 迴圈呼叫 it.__next__()產生 StopIteration 異常時,迴圈結束。

我們們可以用下面的程式碼模擬一下:

>>> a_list = [1,2,3,4]
>>> it = a_list.__iter__()  # 獲取迭代器
>>> it.__next__()           # 讓迭代器返回下一個值
1
>>> it.__next__()
2
>>> it.__next__()
3
>>> it.__next__()
4
>>> it.__next__()    # 迭代器沒有可供返回的值,引發 StopIteration 異常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 






參考資料

【1】《Python基礎教程》(人民郵電出版社,第3版)

【2】 Python 中的黑暗角落(一):理解 yield 關鍵字

相關文章