在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()
方法可以往生成器發送一個值並返回生成器生成的下一個值,下面舉個簡單的栗子來簡單介紹下該方法。
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 3
和receive = 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()
方法提供了調用者與生成器間的通信機制,通過該機制我們可以進行一些特殊操作,當然這也要視需求而定。
參考資料:
以上便是本文的全部內容,要是覺得不錯的話,可以點個贊或關注一下博主,你們的支持是博主創作的不竭動力,當然要是有問題的話也敬請批評指正!!!