Python __iter__和__reversed__:實現疊代器

2020-07-16 10:04:50
前面介紹了使用 for 迴圈遍歷列表、元組和字典等,這些物件都是可疊代的,因此它們都屬於迭代器。

如果開發者需要實現疊代器,只要實現如下兩個方法即可:
  • __iter__(self):該方法返回一個疊代器(iterator),疊代器必須包含一個__next__()方法,該方法返回疊代器的下一個元素。
  • __reversed__(self):該方法主要為內建的 reversed() 反轉函數提供支援,當程式呼叫 reversed() 函數對指定迭代器執行反轉時,實際上是由該方法實現的。

從上面介紹不難看出,如果程式不需要讓疊代器反轉迭代,其實只需要實現第一個方法即可。下面程式將會定義一個代表斐波那契數列(數列的元素等於前兩個元素之和:f(n+2) = f(n+1) +f(n))的疊代器。
# 定義一個代表斐波那契數列的疊代器
class Fibs:
    def __init__(self, len):
        self.first = 0
        self.sec = 1
        self.__len = len
    # 定義疊代器所需的__next__方法
    def __next__(self):
        # 如果__len__屬性為0,結束疊代
        if self.__len == 0:
            raise StopIteration
        # 完成數列計算:
        self.first, self.sec = self.sec, self.first + self.sec
        # 數列長度減1
        self.__len -= 1
        return self.first
    # 定義__iter__方法,該方法返回疊代器
    def __iter__(self):
        return self
# 建立Fibs物件
fibs = Fibs(10)
# 獲取疊代器的下一個元素
print(next(fibs))
# 使用for迴圈遍歷疊代器
for el in fibs:
    print(el, end=' ')
上面程式定義了一個 Fibs 類,該類實現了 __iter__() 方法,該方法返回 self,因此它要求該類必須提供 __next__() 方法,該方法會返回數列的下二個值。程式使用 len 屬性控制數列的剩餘長度,當 __len 為 0 時,程式停止遍歷。
 
上面程式建立了一個長度為 10 的數列,程式開始使用內建的 next() 函數來獲取疊代器的下一個元素,該 next() 函數其實就是通過疊代器的 __next()__ 方法來實現的。

程式接下來使用 for 迴圈來遍歷應數列。執行該程式,將看到如下輸出結果:

1 1 2 3 5 8 13 21 34 55

此外,程式可使用內建的 iter() 函數將列表、元組等轉換成疊代器,例如如下程式碼:
# 將列表轉換為疊代器
my_iter = iter([2, 'fkit', 4])
# 依次獲取疊代器的下一個元素
print(my_iter.__next__()) # 2
print(my_iter.__next__()) # fkit