在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問(wèn)答/Python/ 協(xié)程中委派生成器如何處理子生成器的StopIteration并獲取異常附帶的va

協(xié)程中委派生成器如何處理子生成器的StopIteration并獲取異常附帶的value呢?

本人最近在學(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)
2017年5月17日 14:36
編輯回答
妖妖

對(duì)于這個(gè)問(wèn)題,打開鏈接,里面的總結(jié)部分解釋的很詳細(xì)了

2017年11月1日 06:09