迭代器與生成器:Python高效處理數據的基礎技巧

爲什麼需要迭代器和生成器?

在Python中處理數據時,我們經常會遇到這樣的問題:如果數據量很大(比如幾GB的文件、海量的日誌記錄),或者數據是“無限”的(比如不斷接收的傳感器數據),直接把所有數據加載到內存中會導致程序崩潰,或者運行得非常緩慢。這時候,迭代器和生成器就能派上用場了——它們可以“按需”生成數據,而不是一次性加載所有內容到內存,從而節省內存並提高效率。

一、迭代器:逐個“吐出”數據的對象

什麼是迭代器?
迭代器是一個“數據訪問接口”,它能讓你逐個獲取數據集合中的元素,而且只能向前迭代(不能後退)。它必須實現兩個核心方法:
- __iter__():返回迭代器對象本身(讓for循環能識別它是可迭代的)。
- __next__():返回下一個元素,如果沒有更多元素,會拋出StopIteration異常。

如何創建和使用迭代器?
Python中,幾乎所有可迭代對象(如列表、元組、字符串、字典等)都可以通過iter()函數轉換爲迭代器。例如:

# 定義一個列表
my_list = [1, 2, 3, 4]

# 將列表轉換爲迭代器
my_iter = iter(my_list)

# 逐個獲取元素
print(next(my_iter))  # 輸出:1
print(next(my_iter))  # 輸出:2
print(next(my_iter))  # 輸出:3
print(next(my_iter))  # 輸出:4
print(next(my_iter))  # 報錯:StopIteration(所有元素已迭代完畢)

關鍵點
- 迭代器只能“往前走”,無法重複迭代。比如第一次迭代完後,迭代器已經“走到頭”,再次用next()會直接報錯。
- 常見的可迭代對象(列表、元組等)本身不是迭代器,但可以通過iter()轉換爲迭代器。

二、生成器:更簡單的迭代器,用yield實現

生成器是一種特殊的迭代器,它的語法比手動實現迭代器更簡潔,而且內存效率更高。生成器通過兩種方式創建:生成器函數(用yield關鍵字)或生成器表達式(類似列表推導式,但用圓括號)。

1. 生成器函數:用yield“暫停”和“恢復”

生成器函數和普通函數類似,但使用yield關鍵字替代return。當函數執行到yield時,會暫停執行並返回一個值;下次調用函數時,會從yield的下一行繼續執行。

示例1:生成器函數生成斐波那契數列
斐波那契數列是無限的(0, 1, 1, 2, 3, 5…),如果用列表生成會佔用無限內存,而生成器可以“按需”生成:

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a  # 每次返回一個斐波那契數,暫停函數
        a, b = b, a + b

# 使用生成器
fib = fibonacci(5)  # 生成前5個斐波那契數
for num in fib:
    print(num)  # 輸出:0, 1, 1, 2, 3

示例2:生成器函數處理大文件
如果要讀取一個10GB的日誌文件,用列表一次性讀取會崩潰,而生成器可以逐行讀取:

def read_large_file(file_path):
    with open(file_path, 'r') as f:
        for line in f:  # 文件對象本身是可迭代的,逐行讀取
            yield line.strip()  # 每次返回一行內容

# 使用生成器讀取文件
for line in read_large_file('big_log.txt'):
    process(line)  # 處理每一行數據(無需加載整個文件到內存)
2. 生成器表達式:一行實現簡單生成器

生成器表達式語法與列表推導式類似,但用圓括號()包裹,且不會一次性生成所有元素,而是逐個生成。

示例1:生成1-10的平方數(生成器表達式)

squares = (x**2 for x in range(10))  # 生成器表達式
print(squares)  # 輸出:<generator object <genexpr> at 0x...>

for num in squares:
    print(num)  # 逐個輸出:0, 1, 4, 9, 16, 25, 36, 49, 64, 81

對比列表推導式
列表推導式[x**2 for x in range(10)]會一次性生成包含所有10個平方數的列表,佔用內存;而生成器表達式(x**2 for x in range(10))只會在每次迭代時生成一個數,內存效率更高。

三、迭代器 vs 生成器:核心區別

特性 迭代器 生成器
定義方式 手動實現__iter____next__方法 生成器函數(yield)或生成器表達式
內存效率 較高,但需手動實現 極高,無需一次性存儲所有元素
適用場景 複雜迭代邏輯(如自定義序列) 簡單的“逐個生成”場景(如大數據流)

四、實際應用場景

  1. 處理大數據流:如讀取大文件、處理數據庫查詢結果(避免一次性加載)。
  2. 無限序列:如斐波那契數列、隨機數生成(無法用列表存儲無限數據)。
  3. 節省內存:例如生成100萬個數的平方,用生成器表達式比列表推導式節省大量內存。

五、總結

迭代器和生成器是Python中處理數據的“輕量級”工具,核心優勢是內存高效按需生成。掌握它們能讓你寫出更簡潔、更高效的代碼,尤其在處理大數據或無限序列時。生成器作爲特殊的迭代器,語法更簡單(yield或生成器表達式),是初學者快速上手的優選。

從“逐個訪問元素”到“按需生成數據”,迭代器和生成器讓Python處理數據的能力更上一層樓,是每個Python開發者必備的基礎技巧。

小夜