如何在 Python 中使用生成器(yield 語句)
了解如何用 Python 編寫生成器。了解yield關鍵字、惰性求值、記憶體優化,並將生成器與清單結構進行比較。
概述
當處理大量資料集、日誌檔案或無限資料流時,同時將所有元素載入到記憶體中(例如返回一個大列表)很容易耗盡系統 RAM 並使應用程式崩潰。 Python 提供了一個出色的、節省記憶體的解決方案:生成器。
生成器是一種特殊類型的函數,它會傳回惰性迭代器。生成器不是一次計算所有值並傳回它們,而是根據請求逐一產生值。主要區別在於“yield”聲明。當生成器函數呼叫“yield”時,它會暫停其執行狀態(變數、指令指標)並傳回產生的值。當請求下一個值時,該函數將從暫停處準確恢復。
由於生成器計算是延遲執行的,因此無論資料集大小如何,它們都使用幾乎為零的記憶體。 Python 也支援生成器表達式,它使用括號語法「(x for x in data)」來建立輕量級內嵌產生器,而無需宣告完整函數。
程式碼和執行輸出
此腳本示範了使用生成器函數以及yield 語句和生成器表達式來產生序列。
generators_demo.py
在編輯器中嘗試# 1. Generator function using yield
def count_up_to(limit):
count = 1
while count <= limit:
yield count
count += 1
# Instantiating the generator
counter = count_up_to(3)
print("Memory safe generator instantiated.")
# Fetching values manually
print("Next 1:", next(counter))
print("Next 2:", next(counter))
print("Next 3:", next(counter))
# 2. Iterating with a for loop (automatically handles StopIteration)
print("\n--- Looping over generator ---")
for num in count_up_to(4):
print("Num:", num)
# 3. Generator expression (Shorthand syntax)
squares_gen = (x**2 for x in range(1, 4))
print("\nGenerator expression elements:")
print(list(squares_gen)) # Cast to list to print all elements端子輸出
Memory safe generator instantiated.
Next 1: 1
Next 2: 2
Next 3: 3
--- Looping over generator ---
Num: 1
Num: 2
Num: 3
Num: 4
Generator expression elements:
[1, 4, 9]逐步實施
- 使用標準 def 關鍵字定義函數。
- 使用yield 關鍵字而不是return 將yield 值傳回迭代器流。
- 使用 for 迴圈迭代產生器或呼叫內建的 next(gen) 函數來提取值。
- 使用生成器表達式(使用括號)進行簡單的內聯惰性轉換。
常見問題解答
與清單相比,生成器的主要優點是什麼?
記憶體效率。清單同時將所有元素儲存在 RAM 中,而生成器則根據需要逐一產生項目,從而允許您處理大於系統總記憶體的資料集。
當生成器用完物品時會發生什麼事?
Python 引發 StopIteration 異常。 for 循環會自動捕獲此異常以正常退出循環,但在耗盡的生成器上手動呼叫 next() 將引發異常。
相關主題
推薦的 Python 資源
透過相關的互動式教學、備忘單和程式碼比較來擴展您的知識。