python - 从 python 生成器接收 'return' 值的最佳方法

标签 python generator

自 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 循环更简单的方法?

最佳答案

您可以将 StopIterationvalue 属性(可以说是 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/

相关文章:

python - Numpy 方法返回数组数组中数组出现的索引

python - 将tensorflow添加到requirements.txt时,Azure Python Function App部署失败

python - 如何使用 cv2.rectangle() 创建随机颜色边界框

python - 在什么情况下你应该在 python 中实际使用生成器?

python - 列表推导和生成器表达式中的 yield

entity-framework - Entity Framework 5.0 是否有 ObjectContext 生成器?

python - 一个支持 SSL 的简单 Python IRC 客户端库?

Python - 函数可以在不显式使用名称的情况下调用自身吗?

python - 在 python 中迭代元组中的生成器

python - 生成器表达式和 Any/All 的意外结果