首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么要让StopIteration输出while循环

为什么要让StopIteration输出while循环
EN

Stack Overflow用户
提问于 2019-06-23 03:10:37
回答 2查看 202关注 0票数 1

我正在使用yield from,但我不知道whileyield的影响。如果我将yield from放在一个while循环中,它工作得很好,但是当我同时取消这个循环时,一个异常就会发生。

代码语言:javascript
复制
final_result = {}
def sales_sum(pro_name):
    total = 0
    nums = []
    while True:
        x = yield
        print(pro_name+" Sales volume: ", x)
        if not x:
            break
        total += x
        nums.append(x)
    return total, nums

def middle(key):
    while True:
        final_result[key] = yield from sales_sum(key)

def middle2(key):
    final_result[key] = yield from sales_sum(key)

def main(fun):
    data_sets = { "A": [1200, 1500], "B": [28,55,98]}
    for key, data_set in data_sets.items():
        m = fun(key)
        m.send(None)
        for value in data_set:
            m.send(value)
        m.send(None)

if __name__ == '__main__':
    main(middle) # work well
    main(middle2) # StopIteration

我希望main(middle2)能像main(middle)一样工作得很好,但有一个StopIteration例外。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-23 03:50:27

main中出现意外StopIteration异常的原因是,m.send(None)调用导致middle2生成器耗尽(子生成器sales_sum响应收到的False值而中断循环之后)。当生成器耗尽时,它会引发StopIteration。通常这是不可见的,因为您在for循环中使用迭代器,但在这种情况下,它会破坏您的代码。

有几种方法可以解决这个问题。一种是使用双参数调用next,而不是使用m.send(None)

代码语言:javascript
复制
next(m, None)

这与m.send(None)的作用相同,但具有抑制StopIteration的额外好处。请注意,next调用中的Nonesend中的并不完全相同。在耗尽迭代器的情况下,它是默认返回值,而不是传入的值(使用next时,该值始终为None )。

另一种方法是更改middle2,使其不会在sales_sum生成器结束时结束。您可以在末尾添加一个额外的yield语句,这样当它的子生成器返回时,它会在分配给final_result之后最后一次生成控制权。

最后一个想法是用m.close()取代m.send(None)。这需要对final_result进行一些更改,因为close调用将在生成器中抛出一个GeneratorExit异常。如果你期望它,你可以使用它作为你要做的信号,而不是寻找一个错误的值:

代码语言:javascript
复制
def sales_sum(pro_name):
    total = 0
    nums = []
    while True:
        try:
            x = yield
        except GeneratorExit:
            return total, nums

        print(pro_name+" Sales volume: ", x)
        total += x
        nums.append(x)

有了这一更改,middle2将不需要任何修改。

票数 1
EN

Stack Overflow用户

发布于 2019-06-23 03:49:58

sales_sum是一个有限迭代器。middle2只遍历它一次;middle尝试遍历多次。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56718368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档