Contents

在 Python 中使用生成器

如果您正在從日誌文件中讀取行或處理很長的項目列表,一種選擇是將整個數據加載到內存中。然而,這種方法會使用大量內存並降低性能。發電機提供了一個有價值的解決方案。

生成器減輕了一次性將大量數據加載到內存中的需求。它們在涉及大量數據集、無限級數或任何重視內存管理的情況下特別有用。

什麼是生成器?

/bc/images/wind-energy-generator.jpg

生成器可以定義為一種特定類型的函數,它能夠迭代處理一系列元素。與一次性提供整個數據集的傳統函數相比,生成器根據需要逐步生成各個組件。因此,它們在處理大量或無限的信息集合時非常有效。

標準 Python 函數通常設計用於計算單個值並返回它,而生成器函數則在迭代的基礎上運行。生成器函數不是計算一個值並一次性返回它,而是通過一系列暫停和恢復執行來隨著時間的推移生成多個值。

在編程語言中生成功能通常涉及確定如何生成或執行數據。標準函數和生成器函數在交付結果的方法方面存在根本區別。常規函數通常使用“return”關鍵字作為輸出數據的方式,而生成器函數則依賴“yield”語句來實現此目的。

如何創建生成器

要構造生成器函數,請使用位於函數體內的yield 語句來代替傳統的return 語句。 Yield 關鍵字不僅充當函數產生結果的指令,還使其能夠保留其當前狀態,從而促進潛在的恢復。

當然,這是 Python 中基本生成器函數的一個實例:

 def numeric_generator():
  yield 1
  yield 2
  yield 3

gen = numeric_generator()

這個特定的函數在執行時會產生一系列從 1 到 3 的數字。

Yield 語句在函數式編程中具有獨特的用途,它可以暫停和恢復函數執行,同時保留其當前狀態(包括任何本地定義的變量)以供後續調用。這允許無縫繼續計算,而不需要顯式重新啟動或額外的簿記。

當將生成器函數存儲在變量中時,就會創建一個可用於各種操作的生成器對象。

/bc/images/generator-object.jpg

使用生成器

生成器提供了跨各種上下文的多種應用程序,包括在 for 循環和列表推導式以及更廣泛的迭代結構中使用。此外,生成器適合用作許多函數的輸入參數。

一旦構建了生成器,您就可以使用稱為“for 循環”的循環結構來迭代遍歷其輸出。這使您可以系統地處理函數生成的序列的每個元素,而無需單獨手動訪問和操作它們。

 for i in numeric_generator():
  print(i)

還可以利用後續函數來順序獲取值:

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

通過這種方法可以賦予您對生成器實體更大的影響力。

/bc/images/numeric-generator-in-action.jpg

生成器具有維持其內部狀態的能力。函數中“yield”關鍵字的每個實例都是生成器暫停其進度並記錄其當前位置的機會。在生成器對像上調用“next()”方法時,控制權將轉移回之前的“yield”語句,從而有效地在該特定點恢復執行。

人們還可以利用“send()”方法將數據傳輸到生成器,從而提供值。

 def generator_with_send():
    # First yield: Receive a value
    x = yield
    print(f"Received: {x}")

    # Second yield: Receive another value
    y = yield
    print(f"Received: {y}")

    # Third yield: Yield the sum
    yield x \+ y

gen = generator_with_send()

# Start generator and reach first yield
next(gen)

# Send 10 into generator, received at first yield
result = gen.send(10)

# Send 5 into generator, received at second yield
result = gen.send(5)

# Print result of third yield
print(result) 

Python 生成器中的 send() 方法提供了一種檢索輸出值並通過將值發送回生成器函數來控制執行流程的機制。當需要暫停生成器的執行或編寫涉及多次調用生成器函數的更複雜的協作程序時,此技術非常有用。

/bc/images/sending-values-to-generators.jpg

使用生成器表達式

生成器表達式提供了一種有效的方式,通過使用括號而不是方括號的縮寫語法來製作簡單的無名生成器。它們在許多方麵類似於列表推導式,但表現出與對應結構不同的獨特特徵。

這是一個例子:

 gen = (i**2 for i in range(10))

for x in gen:
  print(x)

該代碼使用生成器表達式構造一個生成器對象,該對像生成範圍從 0 到指定上限的整數的平方。這種方法特別適合在任何給定時間只需要生成一部分輸出的情況,因為它可以按需高效、靈活地生成值。

/bc/images/generator-expressions.jpg

使用生成器進行數據處理

Python 生成器提供了一種優雅的解決方案來描述數據流,同時最大限度地減少內存使用。通過掌握它們的利用率,程序員可以輕鬆有效地處理複雜的數據處理任務。

在處理大量數據集時,明智的做法是考慮利用生成器,因為它們能夠處理繁重的計算任務,同時保持敏捷和簡化的編碼環境。