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

更新於 發佈於 閱讀時間約 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
留言分享你的想法!
小松鼠-avatar-img
2024/09/17
send('烤肉') send('烤玉米') send('蛤蠣湯') send('月餅')
螃蟹_crab-avatar-img
發文者
2024/09/17
小松鼠 暴肥~ 完蛋 體重不知道要增加多少~
avatar-img
螃蟹_crab的沙龍
149會員
284內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。 興趣是攝影,踏青,探索未知領域。 人生就是不斷的挑戰及自我認清,希望老了躺在床上不會後悔自己什麼都沒做。
螃蟹_crab的沙龍的其他內容
2025/04/25
在 Python 中,字典(dict)是非常常用的資料結構,用來儲存 key-value 配對。而在操作字典時,.setdefault() 是一個常被忽略但非常實用的方法。 這篇文章會完整介紹 .setdefault() 的語法、用途、與實務範例,幫助你更有效率地處理字典資料。 什麼是 .se
Thumbnail
2025/04/25
在 Python 中,字典(dict)是非常常用的資料結構,用來儲存 key-value 配對。而在操作字典時,.setdefault() 是一個常被忽略但非常實用的方法。 這篇文章會完整介紹 .setdefault() 的語法、用途、與實務範例,幫助你更有效率地處理字典資料。 什麼是 .se
Thumbnail
2025/01/30
Python 程式在電腦上的執行流程 當我們在電腦上執行 Python 程式時,主要經歷以下幾個步驟: 1. 編寫 Python 程式碼 開發者使用文字編輯器或 IDE(如 VS Code、PyCharm)撰寫 Python 程式,並將其存為 .py 檔案。 例如,一個簡單的 Python
Thumbnail
2025/01/30
Python 程式在電腦上的執行流程 當我們在電腦上執行 Python 程式時,主要經歷以下幾個步驟: 1. 編寫 Python 程式碼 開發者使用文字編輯器或 IDE(如 VS Code、PyCharm)撰寫 Python 程式,並將其存為 .py 檔案。 例如,一個簡單的 Python
Thumbnail
2024/10/17
在一個典型的程式專案中,UI、Controller 和 Main 的分工通常遵循 MVC 模型(Model-View-Controller) 的架構,這是一種常見的設計模式,能夠將應用程式的邏輯和界面進行分離。 大部分典型的程式專案設計: UI (View):專注於用戶界面,展示數據,並將用
Thumbnail
2024/10/17
在一個典型的程式專案中,UI、Controller 和 Main 的分工通常遵循 MVC 模型(Model-View-Controller) 的架構,這是一種常見的設計模式,能夠將應用程式的邏輯和界面進行分離。 大部分典型的程式專案設計: UI (View):專注於用戶界面,展示數據,並將用
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
Thumbnail
在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
我們在學習kafka的過程中最不習慣的就是不管什麼樣的資料, 在kafka的傳輸過程都會是binary的資料格式, 因此我們在撰寫程式的過程中並不是那麼的直觀, 必須將資料從float、int…資料型態轉型成binary才能順利傳送, 那麼基於這樣的前提之下, python這套程式語言可以怎麼做
Thumbnail
我們在學習kafka的過程中最不習慣的就是不管什麼樣的資料, 在kafka的傳輸過程都會是binary的資料格式, 因此我們在撰寫程式的過程中並不是那麼的直觀, 必須將資料從float、int…資料型態轉型成binary才能順利傳送, 那麼基於這樣的前提之下, python這套程式語言可以怎麼做
Thumbnail
※ 靜態資源回傳 ※ 什麼是靜態資源: 定義:是指事先準備好的資源,這些資源在伺服器上是靜態的、不會隨著每個請求而改變。 資源通常包括: 靜態 HTML 文件。 CSS。 圖像(Image)。 Video。 字體文件:google fonts。 favicon:網頁名稱旁邊的ico
Thumbnail
※ 靜態資源回傳 ※ 什麼是靜態資源: 定義:是指事先準備好的資源,這些資源在伺服器上是靜態的、不會隨著每個請求而改變。 資源通常包括: 靜態 HTML 文件。 CSS。 圖像(Image)。 Video。 字體文件:google fonts。 favicon:網頁名稱旁邊的ico
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
Thumbnail
Lua 開檔寫檔的運用 io.output()...
Thumbnail
Lua 開檔寫檔的運用 io.output()...
Thumbnail
當我們在撰寫一套系統的時候, 總是會提供一個介面讓使用者來觸發功能模組並回傳使用者所需的請求, 而傳統的安裝包模式總是太侷限, 需要個別主機獨立安裝, 相當繁瑣, 但隨著時代的演進與互聯網的崛起, 大部分的工作都可以藉由網頁端、裝置端來觸發, 而伺服端則是負責接收指令、運算與回傳結果, 雲端
Thumbnail
當我們在撰寫一套系統的時候, 總是會提供一個介面讓使用者來觸發功能模組並回傳使用者所需的請求, 而傳統的安裝包模式總是太侷限, 需要個別主機獨立安裝, 相當繁瑣, 但隨著時代的演進與互聯網的崛起, 大部分的工作都可以藉由網頁端、裝置端來觸發, 而伺服端則是負責接收指令、運算與回傳結果, 雲端
Thumbnail
設計程式來讀取欲傳送訊息之參數txt檔案,再利用程式自動傳出訊息至LINE群組。能簡易使用於任何場合。
Thumbnail
設計程式來讀取欲傳送訊息之參數txt檔案,再利用程式自動傳出訊息至LINE群組。能簡易使用於任何場合。
Thumbnail
 程式開發,功能 :               本程式執行後,自動寄出email,寄出的內容可依照讀取的參數檔內容而決定
Thumbnail
 程式開發,功能 :               本程式執行後,自動寄出email,寄出的內容可依照讀取的參數檔內容而決定
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News