本人最近在學(xué)習(xí)Python中的協(xié)程知識(shí)。遇到一處委派生成器利用while True處理子生成器的StopIteration并獲取異常附帶的值的代碼例子。
代碼實(shí)例問(wèn)題描述:
在下面的實(shí)例中,我們需要利用委派生成器的知識(shí)將某班級(jí)的男女生身高和體重分別計(jì)算平均值并輸出。第一段代碼是可以算出正確結(jié)果的。
from collections import namedtuple
Result=namedtuple('Result','average number')
def subaverager():#子生成器
total = 0.0
number = 0
average = None
while True:
term = yield
if term is None:
break
total += term
number += 1
average=total/number
return Result(average,number)
def averager(results,key):#委派生成器
while True:
results[key]=yield from subaverager()
def main(grouper):
results={}
for key,group in grouper.items():
term = averager(results,key)
next(term)
for value in group:
term.send(value)
term.send(None)
print(results)#調(diào)試使用
result(results)
def result(results):
for key,value in results.items():
gender,unit=key.split(';')
print('{} {} averaging {:.2f} {}.'.format(
value.number,gender,value.average,unit))
data = {
'girls;kg':
[40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
'girls;m':
[1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
'boys;kg':
[39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
'boys;m':
[1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
}
if __name__=='__main__':
main(data)
正確輸出如下:
{'girls;kg': Result(average=42.040000000000006, number=10)}
{'girls;kg': Result(average=42.040000000000006, number=10), 'girls;m': Result(average=1.4279999999999997, number=10)}
{'girls;kg': Result(average=42.040000000000006, number=10), 'girls;m': Result(average=1.4279999999999997, number=10), 'boys;kg': Result(average=40.422222222222224, number=9)}
{'girls;kg': Result(average=42.040000000000006, number=10), 'girls;m': Result(average=1.4279999999999997, number=10), 'boys;kg': Result(average=40.422222222222224, number=9), 'boys;m': Result(average=1.3888888888888888, number=9)}
10 girls averaging 42.04 kg.
10 girls averaging 1.43 m.
9 boys averaging 40.42 kg.
9 boys averaging 1.39 m.
在第一輪平均值的計(jì)算中,當(dāng)主函數(shù)傳給子生成器None使其終止時(shí),子生成器會(huì)把StopIteration以及第一輪計(jì)算結(jié)果的值返回給委派生成器(就是averager())。我自己寫上述代碼時(shí)沒有像正確代碼一樣,在委派生成器中加入while True。我寫的averager()如下:
def averager(results,key):
results[key]=yield from subaverager()#自己寫委派生成器沒有加while True
如果不添加While True,解釋器報(bào)錯(cuò)StopIteration,主函數(shù)的print(results)也不會(huì)輸出任何字符串。相反,如果添加while True,代碼能夠順利運(yùn)行。
所以我的理解是,委派生成器中的while True能夠處理StopIteration并將異常的值賦給results[key],然后在下一個(gè)循環(huán)的yield from處阻塞。我不清楚這么理解對(duì)不對(duì),懇請(qǐng)明白的前輩幫我指點(diǎn)迷津,感激不盡?。?!
不添加While True 我猜你是不是也沒有執(zhí)行term.send(None),執(zhí)行send(None)可以拿到正確的結(jié)果
try:
term.send(None)
except StopIteration:
pass
沒有send(None)的話subaverager的while True沒有跳出,所以還沒有運(yùn)行到return,averager的yield from沒有等到返回值,當(dāng)然不會(huì)給results[key]賦值,所以results還是空dict
看這樣你能理解么, 加上while True,term.send(None)后results[key]獲得了數(shù)據(jù),之后又運(yùn)行yield from 等待下一個(gè)值,所以averager生成器沒有拋出StopIteration,下一個(gè)值我特意減去了第一個(gè)人,你會(huì)發(fā)現(xiàn)前一個(gè)值被沖掉了,就是字典賦值的證據(jù)
def averager(results,key):
while True:
results[key]=yield from subaverager()
def main(grouper):
results={}
for key,group in grouper.items():
term = averager(results,key)
next(term)
for value in group:
term.send(value)
term.send(None)
for value in group[1:]:
term.send(value)
term.send(None)
result(results)
while True也可以換成yield,看看下面這個(gè)列子
def averager(results,key):
results[key]=yield from subaverager() #等待值
yield #等待,防StopIteration
def main(grouper):
results={}
for key,group in grouper.items():
term = averager(results,key)
next(term)
for value in group:
term.send(value)
term.send(None)
result(results)北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問(wèn),美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。