个人理解:
调用方 .send(None) 后,在 子生成器 break 时抛出 StopIteration 异常,return 返回值后在委托生成器中赋值给 yield from 表达式左侧变量并捕捉 子生成器 抛出的 StopIteration 异常。
问题:
但是为什么此时如果 委托生成器 没有 while True: ,又会抛出 StopIteration 异常?
原代码:
# 子生成器
def average_gen():
total = 0
count = 0
average = 0
while True:
new_num = yield average
if new_num is None:
break
count += 1
total += new_num
average = total/count
# 每一次return,都意味着当前协程结束。
return total,count,average
# 委托生成器
def proxy_gen():
while True:
# 只有子生成器要结束(return)了,yield from左边的变量才会被赋值,后面的代码才会执行。
total, count, average = yield from average_gen()
print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))
# 调用方
def main():
calc_average = proxy_gen()
next(calc_average) # 预激协程
print(calc_average.send(10)) # 打印:10.0
print(calc_average.send(20)) # 打印:15.0
print(calc_average.send(30)) # 打印:20.0
calc_average.send(None) # 结束协程
# 如果此处再调用calc_average.send(10),由于上一协程已经结束,将重开一协程
if __name__ == '__main__':
main()
委托生成器 中 while True: 的作用是什么呢?
为什么去掉 委托生成器 的 while True: 会抛出 StopIteration 异常呢?
或者说,为什么在 委托生成器 中加上 while True: 就不会抛出 StopIteration 异常了呢?
修改后的代码:
# 子生成器
def average_gen():
total = 0
count = 0
average = 0
while True:
new_num = yield average
if new_num is None:
break
count += 1
total += new_num
average = total/count
# 每一次return,都意味着当前协程结束。
return total,count,average
# 委托生成器
def proxy_gen():
# while True:
# 只有子生成器要结束(return)了,yield from左边的变量才会被赋值,后面的代码才会执行。
total, count, average = yield from average_gen()
print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))
# 调用方
def main():
calc_average = proxy_gen()
next(calc_average) # 预激协程
print(calc_average.send(10)) # 打印:10.0
print(calc_average.send(20)) # 打印:15.0
print(calc_average.send(30)) # 打印:20.0
calc_average.send(None) # 结束协程
# 如果此处再调用calc_average.send(10),由于上一协程已经结束,将重开一协程
if __name__ == '__main__':
main()
异常信息:
10.0
15.0
20.0
计算完毕!!
总共传入 3 个数值, 总和:60,平均数:20.0
Traceback (most recent call last):
File "f:\VSCodeSC\python\tempCodeRunnerFile.python", line 35, in <module>
main()
File "f:\VSCodeSC\python\tempCodeRunnerFile.python", line 31, in main
calc_average.send(None) # 结束协程
StopIteration
生成器在return或函数体结束处触发StopIteration异常(和while break无关),如果有return值,作为StopIteration的Value
而 yield from generator 最终会将捕捉到的generator的StopIteration异常的value传递到左方,在这层上,generator的return value 看上去又像是函数返回值了。
同样,外部委托代理也是在return或函数体结束处触发StopIteration异常, 如果有return值,作为StopIteration的Value