python - 不确定为什么 StopIteration 不由“yield from”处理
问题描述
查看“Fluent Python”书中解释“双向隧道”功能的以下示例代码yield from
,我有以下问题。
from collections import namedtuple
Result = namedtuple('Result', 'count average')
# the subgenerator
def averager(): # <1>
total = 0.0
count = 0
average = None
while True:
term = yield # <2>
if term is None: # <3>
break
total += term
count += 1
average = total/count
return Result(count, average) # <4>
# the delegating generator
def grouper(results, key): # <5>
while True: # <6>
results[key] = yield from averager() # <7>
# the client code, a.k.a. the caller
def main(data): # <8>
results = {}
for key, values in data.items():
group = grouper(results, key) # <9>
next(group) # <10>
for value in values:
group.send(value) # <11>
group.send(None) # important! <12>
print("wrapped up grouper")
print(results)
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],
}
为什么将StopIteration
上面的委托生成器替换为以下委托生成器时会出现异常?
def grouper(results, key):
results[key] = yield from averager()
从我目前所了解到的情况来看,理论上删除while True
应该没问题。group.send(None)
将导致averager()
协程break
返回并Result(...)
传递给委托生成器。然后委托生成器将通过将其分配Result(...)
给results[key]
.
但是发生的事情如下。
Traceback (mostrecent call last):
File "coroaverager3.py", line 111, in <module>
main(data)
File "coroaverager3.py", line 83, in main
group.send(None) # important! <12>
StopIteration
有什么见解吗?
解决方案
委托生成器分配给 是对的results[key]
,但这样做并没有完成。它的执行仍在继续,因为它没有地方可以暂停。当然,它会立即从末端掉下来,导致 thesend(None)
上升StopIteration
(因为它没有返回值(来自 a yield
))。
这while True:
是一种添加另一个暂停位置的愚蠢方式;之后的一个额外yield
的yield from
会更明显一些。(如果客户端并不总是知道执行何时完成,它可以提供一个不同于内部生成器提供的值。)
推荐阅读
- node.js - 错误:无法读取 undefined_NodeJS 的属性“名称”
- python - 如何理解 PyMC 模型中“产量”的使用?
- mongodb - 查询期间文档的MongoDB求和字段
- java - 我应该为我的所有方法编写空检查吗?
- python - 如何使用代码单元格中的行号将 Jupyter Notebook 导出为 html
- buffer - s-lang 中的 jed:总是在所有缓冲区中换行
- kubernetes - kubectl 端口转发到另一个端点
- react-native - PanGestureHandler 在 React Native 中的 setState 后立即取消
- php - 如何更改 Apache 中的绝对路径?
- node.js - 如何使用 Node 在 vscode 中调试电报机器人