程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python系列(七):用栗子帶你深入了解生成器的send()方法

編輯:Python

一.問題引入

在Python中,可以使用生成器來一次返回單個元素,從而可以避免大量占用內存。下面例子中計算房價函數house_price便是一個生成器的栗子,該函數接收兩個參數,其中unit_price表示每平方米單價,areas是售賣的房子的面積。

def house_price(unit_price ,areas):
for area in areas:
yield unit_price * area
unit_price = 1
areas = [100, 120, 110, 180]
for price in house_price(unit_price, areas):
print(f"Price: {
price}")
""" Price: 100 Price: 120 Price: 110 Price: 180 """

但是上述函數無法解決一個問題:在生成器調用的過程中,我們想更改計算房價的每平方米單價。因此我們需要一種方法可以更改生成器每次迭代的unit_price參數值,這個需求可以做到嗎?但是的肯定可以。生成器的send()方法就可以解決這個問題。

二.send()方法詳細介紹

生成器的send()方法可以往生成器發送一個值並返回生成器生成的下一個值,下面舉個簡單的栗子來簡單介紹下該方法。

def my_generator():
receive = yield 3
yield f"{
receive}"
myg = my_generator()
print(myg.send(None)) # print(next(myg))與其作用是等同的
# 3
print(myg.send(5))
# 5

首先,解釋下receive = yield 3這行代碼,這行代碼可以拆成兩部分來看,即yield 3receive = yield,前者表示生成一個新的值,後者指接收send()方法傳過來的值。在執行順序上,調用send()方法後會yield 3,當再次調用next()方法時才會完成receive的賦值

send()方法會引發一次next()方法的調用。

然後,再解釋下為啥需要myg.send(None),這是send()方法的低層實現硬性規定的,當首次執行時不允許帶有參數,下面的對應該部分的低層源碼:

if (f->f_lasti == -1) {
 // f_lasti==-1 代表首次執行
if (arg && arg != Py_None) {
 // 首次執行不允許帶有參數
PyErr_SetString(PyExc_TypeError,
"can't send non-None value to a "
"just-started generator");
return NULL;
}
}

在上述栗子中,若去掉myg.send(None),則會報錯:TypeError: can't send non-None value to a just-started generator

三.問題解決

有了send()方法,我們現在給出第一節中問題的解決方案:

def house_price(areas):
unit_price = yield # 接收初始的unit_price
for area in areas:
unit_price = yield unit_price * area
unit_prices = [1, 2, 3, 1]
areas = [100, 120, 110, 180]
hp = house_price(areas)
hp.send(None) # 啟動生成器
for unit_price in unit_prices:
cur_price = hp.send(unit_price)
print(f"Price: {
cur_price}")
""" Price: 100 Price: 240 Price: 330 Price: 180 """

可以看到通過send()方法,我們可以為每個交易指定一個房價。

結語

從前面的介紹可以看出:send()方法提供了調用者與生成器間的通信機制,通過該機制我們可以進行一些特殊操作,當然這也要視需求而定。

參考資料:

  • Python Generator 生成器的send方法到底有啥用?
  • 為什麼python的yield第一次不能用send發送數據?

以上便是本文的全部內容,要是覺得不錯的話,可以點個贊或關注一下博主,你們的支持是博主創作的不竭動力,當然要是有問題的話也敬請批評指正!!!


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved