自 Python 3.3 起,如果生成器函数返回一个值,该值将成为引发的 StopIteration 异常的值。这可以通过多种方式收集:
yield from
表达式的值,这意味着封闭函数也是一个生成器。- 在 try/except block 中包装对
next()
或.send()
的调用。
但是,如果我只是想在 for 循环中迭代生成器(最简单的方法),似乎没有办法收集 StopIteration 异常的值,从而收集返回值。我使用一个简单的示例,其中生成器生成值,并在最后返回某种摘要(运行总计、平均值、时间统计等)。
for i in produce_values():
do_something(i)
values_summary = ....??
一种方法是自己处理循环:
values_iter = produce_values()
try:
while True:
i = next(values_iter)
do_something(i)
except StopIteration as e:
values_summary = e.value
但这抛弃了 for 循环的简单性。我不能使用 yield from
因为这要求调用代码本身就是一个生成器。有没有比上面显示的 roll-ones-own for 循环更简单的方法?
最佳答案
您可以将 StopIteration
的 value
属性(可以说是 StopIteration
本身)视为实现细节,而不是设计用于“正常”代码。
看看PEP 380指定 Python 3.3 的 yield from
功能:它讨论了一些使用 StopIteration
来携带返回值的替代方案。
由于您不应该在普通的 for
循环中获取返回值,因此没有针对它的语法。与您不应该显式捕获 StopIteration
的方式相同。
针对您的情况,一个不错的解决方案是一个小型实用程序类(对于标准库可能足够有用):
class Generator:
def __init__(self, gen):
self.gen = gen
def __iter__(self):
self.value = yield from self.gen
这会包装任何生成器并捕获其返回值以便稍后检查:
>>> def test():
... yield 1
... return 2
...
>>> gen = Generator(test())
>>> for i in gen:
... print(i)
...
1
>>> print(gen.value)
2
关于python - 从 python 生成器接收 'return' 值的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34073370/