首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

深度解析 Python 迭代器與生成器:從原理到實戰

     編輯:更多程式設計知識

迭代器與生成器是 Python 中處理數據流、實現惰性計算的核心機制。它們不僅統一了容器訪問接口,更能以極低的內存開銷處理海量甚至無限數據流。本文從概念、協議、實現到進階應用,為你全景式拆解這對「黃金搭檔」。

迭代器:統一訪問協議的基石

迭代器是實現迭代器協議的對象,僅需定義兩個方法:

  • __iter__():返回迭代器對象本身
  • __next__() (Python 3) / next() (Python 2):返回下一個元素,耗盡時拋出 StopIteration
>>> i = iter('abc')
>>> next(i)
'a'
>>> next(i)
'b'
>>> next(i)
'c'
>>> next(i)
Traceback (most recent call last):
  ...
StopIteration

自定義迭代器類

class Countdown:
    def __init__(self, start):
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < 0:
            raise StopIteration
        val = self.current
        self.current -= 1
        return val

for n in Countdown(3):
    print(n)  # 3, 2, 1, 0

迭代器的核心優勢

  1. 統一接口:任何實現 __iter__ 的對象均可用 for 循環遍歷,無論底層是列表、集合、文件還是數據庫游標。
  2. 惰性計算:元素僅在被請求時產生,無需一次性載入內存。這使得處理 GB 級日誌文件、無限數列(如費波那契數列)成為可能。
  3. 節省內存:對比列表佔用 O(N) 空間,迭代器僅佔用 O(1) 常數空間。

生成器:語法糖背後的協程機制

生成器是創建迭代器的「語法糖」,核心關鍵字是 yield。包含 yield 的函數調用時不會立即執行,而是返回一個生成器對象。

生成器函數示例:無限費波那契數列

def fibonacci():
    a, b = 0, 1
    while True:
        yield b
        a, b = b, a + b

fib = fibonacci()
print(next(fib))  # 1
print(next(fib))  # 1
print([next(fib) for _ in range(10)])  # [2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

生成器表達式

類似列表推導式,將方括號改為圓括號即可:

>>> squares = (x * x for x in range(10))
>>>> squares
 at 0x...>
>>>> for n in squares:
...     print(n)
0, 1, 4, 9, 16, 25, 36, 49, 64, 81

yield 的進階特性:雙向通信與協程

yield 不僅能「產出」值,還能通過 send() 接收外部傳入的值,實現雙向數據流,這是協程的基礎:

def psychologist():
    print('請說出你的煩惱')
    while True:
        answer = (yield)  # 接收 send() 傳入的值
        if answer is not None:
            if answer.endswith('?'):
                print("別問自己太多問題")
            elif 'good' in answer:
                print("很好,繼續說")
            elif 'bad' in answer:
                print("別太消極")

free = psychologist()
next(free)           # 啟動生成器,輸出「請說出你的煩惱」
free.send('我感覺很糟')   # 輸出「別太消極」
free.send("為什麼我不該這樣?") # 輸出「別問自己太多問題」
free.send("好吧,我要找點好事") # 輸出「很好,繼續說」

此處 yield 暫停函數執行並保存上下文(局部變量、指令指針),下次 next() 或 send() 時從暫停處恢復,這正是「微線程」協程的運行模型。

生成器管道化處理:組合式編程

多個生成器可串聯形成數據處理管道,代碼清晰且內存高效:

def power(values):
    for v in values:
        print(f'powering {v}')
        yield v

def adder(values):
    for v in values:
        print(f'adding to {v}')
        yield v + 3 if v % 2 == 0 else v + 2

elements = [1, 4, 7, 9, 12, 19]
res = adder(power(elements))  # 管道組合
print(next(res))  # powering 1 -> adding to 1 -> 3
print(next(res))  # powering 4 -> adding to 4 -> 7

這種「拉取式」流處理模式,是大數據框架(如 Spark RDD、Flink DataStream)的核心思想縮影。

總結:何時選擇哪一種?

場景推薦方案理由
簡單序列轉換/過濾生成器表達式語法簡潔,一行搞定
複雜狀態邏輯/無限序列生成器函數可維護局部狀態,邏輯清晰
需重複遍歷/隨機訪問列表/元組生成器只能一次性消費
自定義容器類型實現 __iter__/__next__ 類完全控制迭代行為
雙向通信/狀態機基於 yield 的協程天然支持暫停/恢復/傳值

掌握迭代器與生成器,意味著你擁有了處理數據流的「瑞士軍刀」——無論是解析超大 JSON、流式處理視頻幀,還是構建異步任務調度器,都能以優雅、高效、Pythonic 的方式落地。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved