[Python]通過send() 方法向生成器內部傳遞數據

更新於 2024/09/17閱讀時間約 1 分鐘

生成器本身是一種只能輸出數據的結構,它不像列表或其他容器可以存儲數據並操作。它是一種(lazy evaluation)輸出數據的結構,生成器僅在需要時生成數據。因此,它對於處理大數據集或無限序列時非常高效。

然而,生成器與列表或其他容器不同的一個特點是,生成器通常只能輸出數據,但在某些情況下,我們希望生成器能夠根據外部的輸入來動態生成新的結果。這就是 send() 方法的作用。

在 Python 中,可以通過生成器的 send() 方法向生成器內部傳遞數據。


生成器的工作機制:

  1. 生成器函數的定義: 生成器函數定義與普通函數類似,但它使用 yield 來返回數據。
  2. yield 暫停與恢復執行: 當生成器函數執行到 yield,它會暫停並返回當前值。下一次調用生成器(通過 next()send())時,會從暫停處繼續執行。
  3. send() 傳送數據: 除了使用 next() 獲取下一個 yield 的值,還可以用 send(value) 將數據發送給生成器。在 yield 表達式處,生成器會接收到 send() 發送的值並進行處理。

示例:

def my_generator():
value = 0
while True:
received = yield value
if received is not None:
value = received
else:
value += 1

gen = my_generator()

# 獲取生成器的初始值
print(next(gen)) # Output: 0

# 透過 send() 傳遞數據給生成器
print(gen.send(10)) # Output: 10

# 不傳送數據,生成器繼續計算
print(next(gen)) # Output: 11

解釋:

  1. next(gen):啟動生成器,返回初始值 0
  2. gen.send(10):將 10 傳送給生成器,接收 yield,此時生成器內部變量 value 被設置為 10
  3. next(gen):當沒有傳送新值時,生成器默認將 value1,所以輸出為 11

常見用途:

  1. 協程:生成器協程允許生成器與外部代碼動態通信。
  2. 事件驅動編程:在多步處理過程中,動態接收和處理輸入。
  3. 數據流處理:生成器可以根據外部輸入即時計算,避免一次性加載所有數據。

「生成器協程」、「事件驅動編程」、「數據流處理」的 生成器簡單範例


1. 協程(生成器協程允許生成器與外部代碼動態通信)

協程是生成器的擴展,它可以讓你動態接收來自外部的數據並進行處理。

def coroutine_example():
print("協程啟動")
while True:
received = yield
print(f"接收到的數據: {received}")

# 啟動生成器協程
gen = coroutine_example()
next(gen) # 啟動協程
gen.send("第一個數據")
gen.send("第二個數據")
raw-image

解釋:

  • coroutine_example 是一個協程,它通過 yield 暫停,並等待 send() 傳送的數據。每次 send() 傳送後,協程內部會打印接收到的數據。


2. 事件驅動編程(在多步處理過程中,動態接收和處理輸入)

生成器可以用於事件驅動的場景,接收外部事件並根據事件狀態進行操作。

def event_driven_generator():
print('開始接收外部事件')
event_count = 0
while True:
event = yield event_count
if event == "click":
event_count += 1
elif event == "reset":
event_count = 0
print(f"事件數量: {event_count}")

gen = event_driven_generator()
next(gen) # 啟動生成器

# 模擬事件
gen.send("click")
gen.send("click")
gen.send("reset")
gen.send("click")
raw-image

解釋:

  • event_driven_generator 生成器接收不同的事件,例如「click」或「reset」。每次收到「click」事件時,會遞增計數,收到「reset」時重置計數。


3. 數據流處理(生成器可以根據外部輸入即時計算,避免一次性加載所有數據)

這個範例展示了如何利用生成器進行數據流處理,動態生成數據而不是一次性加載。

def data_stream_processor(data):
print(f'接收資料')
total = 0
for item in data:
total += item
print(f'處理第{item}個資訊 :{total}')
processed_value = yield total
if processed_value is not None:
total = processed_value
print(f'處理接收的資訊 :{total}')

gen = data_stream_processor([1, 2, 3, 4, 5])
print(next(gen)) # 處理第一個數據
print(gen.send(10)) # 更新總和為 10 並繼續
print(next(gen)) # 繼續處理
print(next(gen)) # 繼續處理
print(gen.send(10)) # 更新總和為 10 並繼續
raw-image

解釋:

  • 接收資料:當你調用這個生成器時,它會接收一個 data 列表作為輸入。
  • total:這是一個累加變數,初始值為 0,用來計算資料的總和。
  • for item in data:生成器逐步處理 data 列表中的每個項目,每次迭代會將當前的項目 item 加到 total 中。
  • yield total:這行代碼會返回目前的 total 值,同時生成器會暫停並等待下一個操作(通過 next()send())。
  • processed_value = yield total:這允許外部使用 send() 方法傳入數據。傳入的數據會賦值給 processed_value。如果 processed_value 不是 None,則生成器會更新 total 的值,這樣可以動態調整累加的結果。

執行步驟

gen = data_stream_processor([1, 2, 3, 4, 5])

這行程式碼會創建生成器對象 gen,並將列表 [1, 2, 3, 4, 5] 傳遞給它。

print(next(gen))  # 處理第一個數據
  • next(gen) 會啟動生成器的執行,並讓它跑到第一個 yield 位置。
  • 它會處理列表中的第一個項目 1,計算總和 total = 1,並暫停在 yield
  • 輸出:
    接收資料
    處理第1個資訊 :1
    1
print(gen.send(10))  # 更新總和為 10 並繼續
  • 這裡調用 send(10),傳入的數值 10 會作為 processed_value,並影響生成器的執行。
  • 生成器接收到 processed_value = 10,所以 total 會更新為 10,然後繼續處理下一個數據(第 2 項 2)。
  • 總和變為 total = 10 + 2 = 12,並暫停在 yield
  • 輸出:
    處理接收的資訊 :10
    處理第2個資訊 :12
    12
print(next(gen))  # 繼續處理
  • 再次使用 next(gen),生成器會從暫停處繼續執行,處理第三個數據 3,總和更新為 total = 12 + 3 = 15
  • 輸出:
    處理第3個資訊 :15
    15
print(next(gen))  # 繼續處理
  • 生成器繼續處理第四個數據 4,總和變為 total = 15 + 4 = 19
  • 輸出:
    處理第4個資訊 :19
    19
print(gen.send(10))  # 更新總和為 10 並繼續
  • 最後,使用 send(10) 再次將 total 更新為 10,然後處理最後一個數據 5,最終總和變為 total = 10 + 5 = 15
  • 輸出:
    處理接收的資訊 :10
    處理第5個資訊 :15
    15

總結:

  • 生成器 data_stream_processor 逐步處理列表中的數據,並且允許通過 send() 動態修改內部狀態(即 total)。
  • 每次 yield 都會暫停生成器的執行,等待外部的操作(next()send()),並根據外部數據更新狀態。


總結:

  • 生成器 data_stream_processor 逐步處理列表中的數據,並且允許通過 send() 動態修改內部狀態(即 total)。
  • 每次 yield 都會暫停生成器的執行,等待外部的操作(next()send()),並根據外部數據更新狀態。





avatar-img
128會員
209內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
生成器表達式是 Python 中一種更簡潔的語法,專門用來創建生成器。它的語法與列表生成式類似,但將列表生成式中的方括號 [] 替換為小括號 ()。生成器表達式與生成器函數類似,具有「惰性評估」的特性,因此它只在需要時才生成元素,從而節省記憶體。 生成器的「惰性評估」(也叫延遲求值)指的是生成器不
呈上篇[Python基礎]類別繼承(Inheritance) 中使用的super()並加以說明,此篇文章主要敘述使用super()有什麼好處及優點。 super():是一個內建函數,用來返回父類別的物件,以便你可以使用這個物件來呼叫父類別的方法或屬性。 這種做法的目的是在子類別中繼承並延續父類別
上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
在 Python 中,tuple 與 List有一個關鍵的不同點:tuple 是不可變的,這意味著一旦創建了 tuple,就無法更改其內容。 這與 List的可變性形成了對比,list 可以新增、刪除或修改元素。 元素的意思: 元素:指的是 List 中的每一個獨立的項目或值。
在離線環境需要安裝Python套件時就相當的麻煩,需要先下載好套件包,在打指令安裝,若套件數量一多時就會相當麻煩。 本文將介紹如何利用兩行指令快速的安裝整個資料夾的套件。
在Python中,import是一個關鍵字,用於將其他模組或套件中的程式碼引入到當前的程式中以供使用。 這個關鍵字允許你在你的程式中使用其他地方定義的變數、函式和類等。 當你使用import時,Python會搜索指定模組或套件的位置,並將其中的程式碼載入到你的程式中,這樣你就可以在程式中使用它們
生成器表達式是 Python 中一種更簡潔的語法,專門用來創建生成器。它的語法與列表生成式類似,但將列表生成式中的方括號 [] 替換為小括號 ()。生成器表達式與生成器函數類似,具有「惰性評估」的特性,因此它只在需要時才生成元素,從而節省記憶體。 生成器的「惰性評估」(也叫延遲求值)指的是生成器不
呈上篇[Python基礎]類別繼承(Inheritance) 中使用的super()並加以說明,此篇文章主要敘述使用super()有什麼好處及優點。 super():是一個內建函數,用來返回父類別的物件,以便你可以使用這個物件來呼叫父類別的方法或屬性。 這種做法的目的是在子類別中繼承並延續父類別
上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
在 Python 中,tuple 與 List有一個關鍵的不同點:tuple 是不可變的,這意味著一旦創建了 tuple,就無法更改其內容。 這與 List的可變性形成了對比,list 可以新增、刪除或修改元素。 元素的意思: 元素:指的是 List 中的每一個獨立的項目或值。
在離線環境需要安裝Python套件時就相當的麻煩,需要先下載好套件包,在打指令安裝,若套件數量一多時就會相當麻煩。 本文將介紹如何利用兩行指令快速的安裝整個資料夾的套件。
在Python中,import是一個關鍵字,用於將其他模組或套件中的程式碼引入到當前的程式中以供使用。 這個關鍵字允許你在你的程式中使用其他地方定義的變數、函式和類等。 當你使用import時,Python會搜索指定模組或套件的位置,並將其中的程式碼載入到你的程式中,這樣你就可以在程式中使用它們
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
Thumbnail
在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
我們在學習kafka的過程中最不習慣的就是不管什麼樣的資料, 在kafka的傳輸過程都會是binary的資料格式, 因此我們在撰寫程式的過程中並不是那麼的直觀, 必須將資料從float、int…資料型態轉型成binary才能順利傳送, 那麼基於這樣的前提之下, python這套程式語言可以怎麼做
Thumbnail
※ 靜態資源回傳 ※ 什麼是靜態資源: 定義:是指事先準備好的資源,這些資源在伺服器上是靜態的、不會隨著每個請求而改變。 資源通常包括: 靜態 HTML 文件。 CSS。 圖像(Image)。 Video。 字體文件:google fonts。 favicon:網頁名稱旁邊的ico
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
Thumbnail
Lua 開檔寫檔的運用 io.output()...
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
Python 產生器(Generator)是一種特殊的迭代器,能夠以更有效率的方式處理大量數據。本文將介紹產生器的基礎概念、使用方法,並提供實際應用範例
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
Thumbnail
在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
我們在學習kafka的過程中最不習慣的就是不管什麼樣的資料, 在kafka的傳輸過程都會是binary的資料格式, 因此我們在撰寫程式的過程中並不是那麼的直觀, 必須將資料從float、int…資料型態轉型成binary才能順利傳送, 那麼基於這樣的前提之下, python這套程式語言可以怎麼做
Thumbnail
※ 靜態資源回傳 ※ 什麼是靜態資源: 定義:是指事先準備好的資源,這些資源在伺服器上是靜態的、不會隨著每個請求而改變。 資源通常包括: 靜態 HTML 文件。 CSS。 圖像(Image)。 Video。 字體文件:google fonts。 favicon:網頁名稱旁邊的ico
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
Thumbnail
Lua 開檔寫檔的運用 io.output()...
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
Python 產生器(Generator)是一種特殊的迭代器,能夠以更有效率的方式處理大量數據。本文將介紹產生器的基礎概念、使用方法,並提供實際應用範例