本人最近在学习Python中的协程知识。在感叹yield from构造的委派生成器能够连通子生成器和待处理数据的同时,遇到一处细节苦思不解,下面详述我的问题。
问题描述:
在下面的实例中,我们需要利用委派生成器的知识将某班级的男女生身高和体重分别计算平均值并输出。下面的代码是可以算出正确结果的。
但是我不理解,委派生成器(就是averager())在每次传输给子生成器数据的并接受子生成器反馈的过程中,对应的while True循环是如何停止并进入新一轮平均值的计算的呢?是因为子生成器break的影响吗?
希望明白的前辈帮忙指点,感激不尽!!!
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)
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)
输出如下:
10 girls averaging 42.04 kg.
10 girls averaging 1.43 m.
9 boys averaging 40.42 kg.
9 boys averaging 1.39 m.
averager的while True并没有停止,而是main的for循环停止了,所以没有在next(term)。averager因为while true生成器不会停止,你可以一直next(term)。新的一轮计算是因为
term = averager(results,key)
又构造了一个新的生成器。去掉while true版本,有值啊,你怎么写的?