当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《从python生成器接收'return'值的最佳方法》经验,为你挑选了2个好方法。

从Python 3.3开始,如果生成器函数返回一个值,那么它将成为引发的StopIteration异常的值.这可以通过多种方式收集:

yield from表达式的值,暗示封闭函数也是一个生成器.

将调用包含在try/except块中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-one-own for循环更简单的方法?

答案摘要

结合@Chad S.和@KT的答案,最简单的似乎是使用迭代器协议将我的生成器函数转换为类:

class ValueGenerator():
    def __iter__(self):
        yield 1
        yield 2
        # and so on
        self.summary = {...}

vg = ValueGenerator()
for i in vg:
    do_something(i)
values_summary = vg.summary

如果我不能重构价值生产者,@ Ferdinand Beyer的答案是最简单的.



1> Ferdinand Be..:

您可以valueStopIteration(并且可以说是StopIteration本身)的属性视为实现细节,而不是设计用于"普通"代码.

看看PEP 380,它指定了yield fromPython 3.3 的特性:它讨论了一些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



2> KT...:

您可以创建一个帮助程序包装器,它将捕获StopIteration并为您提取值:

from functools import wraps

class ValueKeepingGenerator(object):
    def __init__(self, g):
        self.g = g
        self.value = None
    def __iter__(self):
        self.value = yield from self.g

def keep_value(f):
    @wraps(f)
    def g(*args, **kwargs):
        return ValueKeepingGenerator(f(*args, **kwargs))
    return g

@keep_value
def f():
    yield 1
    yield 2
    return "Hi"

v = f()
for x in v:
    print(x)

print(v.value)

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有