Python 的 Iterator 與 Generator 有何不同?實作方式與應用範例

1. 前言

Python 是一種語法簡潔且直觀的程式語言,但若想更有效率地處理資料,就必須理解「疊代器(iterator)」的概念。本文將從疊代器的基本概念、實際用法,到應用範例,為您詳細解說。

2. 可疊代物件與疊代器的基礎

在 Python 中,資料處理時最重要的概念之一就是 「可疊代物件(iterable)」「疊代器(iterator)」。了解這兩者的差異,能幫助您掌握 for 迴圈的內部運作,以及進階的資料處理技巧。

什麼是可疊代物件?

可疊代物件(iterable) 是指可以被反覆處理的物件。在 Python 中,像是 list(串列)、tuple(元組)、dict(字典)、set(集合)以及字串等,都是可疊代物件。

您可以使用 for 迴圈依序取出這些物件中的每個元素。

# list(可疊代物件)的範例
numbers = [1, 2, 3, 4, 5]

for num in numbers:
    print(num)

如上所示,串列 numbers 可以透過 for 迴圈輕鬆處理。在 Python 的 for 迴圈內部,其實是先將可疊代物件轉換成疊代器,再依序取得每個元素。

什麼是疊代器?

疊代器(iterator) 是一種用來從可疊代物件中逐一取出元素的機制或物件。在 Python 中,可以使用 iter() 函式,將可疊代物件轉換成疊代器。

numbers = [1, 2, 3, 4, 5]
iterator = iter(numbers)  # 建立疊代器

print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3

透過呼叫 next(iterator),可以依序取得串列中的元素。

年収訴求

3. Python 中的疊代器運作原理

在 Python 中,疊代器是透過擁有特定方法的物件來實現的。

__iter__()__next__() 的角色

疊代器物件具備以下兩個特殊方法:

  • __iter__():回傳物件本身
  • __next__():回傳下一個元素,若已無元素則拋出 StopIteration 例外

舉例來說,若使用串列手動建立疊代器,程式碼如下:

class CustomIterator:
    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
        value = self.current
        self.current += 1
        return value

# 建立疊代器
custom_iter = CustomIterator(1, 5)

for num in custom_iter:
    print(num)  # 依序輸出 1, 2, 3, 4

如上所示,透過自訂的疊代器類別,我們可以使用 for 迴圈依序取得資料。

4. 如何在 Python 中實作疊代器

在 Python 中,我們可以自訂疊代器的實作方式,讓資料處理更加靈活。本章將詳細介紹以下幾個主題:自訂疊代器類別的建立方式使用生成器函式活用生成器表達式

建立自訂的疊代器類別

在 Python 中,只要建立一個同時擁有 __iter__() 方法與 __next__() 方法的類別,就可以成為一個疊代器。
以下範例會建立一個能從指定起始數字數到結束數字的疊代器:

class Counter:
    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  # 結束時拋出例外
        value = self.current
        self.current += 1
        return value

# 建立疊代器並使用 for 迴圈
counter = Counter(1, 5)
for num in counter:
    print(num)  # 輸出 1, 2, 3, 4, 5

重點說明:

  • __iter__() 方法回傳 self(因為這個類別本身就是疊代器)
  • __next__() 方法會回傳目前的值,並將內部狀態更新為下一個值
  • 當沒有更多資料時,拋出 StopIteration,通知迴圈結束

透過這種方式,我們可以自訂疊代器來進行資料流處理等各種應用。

活用生成器函式

在 Python 中,可以使用 生成器函式(generator function) 來快速建立疊代器。
透過 yield 指令,可以輕鬆產生逐步回傳的資料。

def counter(start, end):
    current = start
    while current <= end:
        yield current  # 回傳值並保留執行狀態
        current += 1

# 使用生成器函式
for num in counter(1, 5):
    print(num)  # 輸出 1, 2, 3, 4, 5

生成器函式的優點:

  • 使用 yield 可以保留狀態並在下次繼續執行
  • 可以節省記憶體,逐步取得需要的資料(延遲評估)

這種方法在處理 大型資料或串流資料 時特別實用。

使用生成器表達式

Python 提供一種語法簡潔的方式來建立生成器,那就是 生成器表達式(generator expression),語法與串列生成式類似。

# 串列生成式(會一次產生所有元素並存入記憶體)
numbers_list = [x * 2 for x in range(1, 6)]
print(numbers_list)  # [2, 4, 6, 8, 10]

# 生成器表達式(延遲生成元素以節省記憶體)
numbers_gen = (x * 2 for x in range(1, 6))

print(next(numbers_gen))  # 2
print(next(numbers_gen))  # 4

生成器表達式的優點:

  • 比串列生成式更節省記憶體
  • 只計算需要的元素,支援延遲評估

在處理大量資料時,使用生成器表達式能有效提升效能與記憶體利用率。

RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

5. 疊代器的應用範例

透過使用疊代器,我們可以高效地實作各種資料處理功能。本章將介紹 3 個實務中常見的應用案例

① 逐行讀取大型檔案

處理大型檔案時,若一次性讀取整個內容會佔用大量記憶體。
透過疊代器,我們可以逐行處理檔案,提升效能。

def read_large_file(file_path):
    with open(file_path, "r", encoding="utf-8") as file:
        for line in file:
            yield line.strip()  # 每行資料逐步處理

# 使用方式
for line in read_large_file("data.txt"):
    print(line)

優點:

  • 節省記憶體,也能處理大型檔案
  • 適合用於資料串流(streaming)處理

② 產生無限序列

使用疊代器可以輕鬆產生無限長度的序列,且不會占用太多資源。

def infinite_counter(start=0):
    while True:
        yield start
        start += 1

# 限制迴圈次數以避免無限執行
counter = infinite_counter()
for _ in range(5):
    print(next(counter))  # 輸出 0, 1, 2, 3, 4

應用情境:

  • 依時間推移產生資料(如時間戳記)
  • 處理感測器的即時輸出資料

③ 處理資料串流(Streaming)

在從 API 或資料庫取得資料時,使用疊代器可以逐筆處理每筆資料,提升彈性與效能。

import time

def api_simulation():
    for i in range(1, 6):
        time.sleep(1)  # 模擬 API 回應時間
        yield f"Data {i}"

# 逐步取得 API 回傳資料
for data in api_simulation():
    print(data)

重點:

  • 可即時取得與處理資料,提升反應速度
  • 減輕網路與系統資源的負擔

6. 使用疊代器時的注意事項

Python 的疊代器非常實用,但若使用方式不當,可能會出現預期外的行為。本章將說明使用疊代器時應注意的 三個重點:「StopIteration 的處理」「疊代器的不可重複使用」「記憶體效率與延遲評估」

① StopIteration 的處理方式

當使用 next() 操作疊代器並取完所有元素後,系統會拋出 StopIteration 例外。

numbers = [1, 2, 3]
iterator = iter(numbers)

print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
print(next(iterator))  # 會拋出 StopIteration

建議的處理方式是使用 try-except 來捕捉這個例外。

numbers = [1, 2, 3]
iterator = iter(numbers)

while True:
    try:
        print(next(iterator))
    except StopIteration:
        print("疊代器已經結束")
        break

補充說明:

  • 使用 for 迴圈時,StopIteration 會自動處理,不需手動處理
  • 手動使用 next() 時,建議使用 try-except 以避免錯誤

② 疊代器無法重複使用

在 Python 中,疊代器一旦被取用完畢,就無法重複使用

numbers = [1, 2, 3]
iterator = iter(numbers)

for num in iterator:
    print(num)  # 輸出 1, 2, 3

for num in iterator:
    print(num)  # 不會有任何輸出(疊代器已經耗盡)

若要再次使用疊代器,您需要重新建立一個新的疊代器

numbers = [1, 2, 3]

# 建立新的疊代器
iterator1 = iter(numbers)
iterator2 = iter(numbers)

print(list(iterator1))  # [1, 2, 3]
print(list(iterator2))  # [1, 2, 3]

補充說明:

  • list 等可疊代物件可以重複使用,但疊代器本身只能使用一次
  • 如需再次使用,請重新呼叫 iter()

③ 記憶體效率與延遲評估

使用疊代器或生成器可以大幅降低記憶體使用量,實現更有效率的資料處理。
以下範例比較 list 與 generator 的差異:

# 使用 list(會將所有元素儲存在記憶體中)
numbers_list = [x * 2 for x in range(1000000)]  # 一百萬筆資料

# 使用生成器(僅在需要時才生成元素)
numbers_gen = (x * 2 for x in range(1000000))

print(sum(numbers_list))  # 計算總和,list 仍佔用記憶體
print(sum(numbers_gen))   # 計算總和但節省記憶體

補充說明:

  • list 會將所有資料一次放入記憶體,適用於小型資料
  • 生成器 採用延遲評估(lazy evaluation),只在需要時才生成元素
年収訴求

7. 常見問題(FAQ)

最後,我們整理了關於 Python 疊代器的一些常見問題與解答。

Q1. 疊代器與生成器有什麼不同?

A:

  • 疊代器是實作了 __iter__()__next__() 方法的類別
  • 生成器是使用 yield 關鍵字撰寫的函式,可以自動建立疊代器
  • 使用生成器可以讓程式碼更簡潔、更易讀

Q2. 為什麼需要 __iter__()__next__() 方法?

A:

  • __iter__() 是 Python 在使用 for 迴圈時會呼叫的方法,用來取得疊代器物件
  • __next__() 是用來取得下一個元素的方法
  • 因為 Python 的 for 迴圈內部就是靠 iter()next() 來運作的

Q3. 使用疊代器有什麼優點?

A:

  • 記憶體使用效率高(特別適合處理大量資料)
  • 支援延遲評估(只在需要時才產生資料)
  • 非常適合串流資料處理(例如處理 API 回應或檔案逐行讀取)

Q4. 什麼情況下需要手動實作疊代器?

A:

  • 當您需要自訂資料處理邏輯(例如:只回傳符合特定條件的資料)
  • 處理串流資料,例如從 API 即時取得資料
  • 需要產生無限序列時(例如持續計數)

Q5. 疊代器與 for 迴圈的關係是什麼?

A:

  • for 迴圈會自動呼叫 iter() 來取得疊代器,並使用 next() 逐一取出元素
  • for 也會自動處理 StopIteration 的例外,因此不容易出錯

總結

在本文中,我們深入介紹了 Python 中的疊代器,從基礎概念到實際應用,幫助你全面掌握這個強大功能。
以下是重點回顧:

疊代器是一種可逐步取出資料的物件
只要實作 __iter__()__next__() 方法,就能建立自訂的疊代器
使用生成器(yield)可以更簡單地實作疊代器
透過延遲評估(lazy evaluation),疊代器能大幅提升記憶體效率
在處理 API 回應、串流資料、檔案操作等場景特別實用

掌握 Python 的疊代器後,您將能以更高效、更靈活的方式處理資料。建議您親自動手實作範例程式碼,進一步加深理解與應用能力!