【问题标题】:Python PEP479 Change StopIteration handling inside generatorsPython PEP479 更改生成器内的 StopIteration 处理
【发布时间】:2016-10-08 23:57:42
【问题描述】:

有人可以帮我理解 PEP479 是关于什么的吗?我正在阅读文档,但无法理解它。

摘要说:

此 PEP 建议对生成器进行更改:当在生成器中引发 StopIteration 时,它会被 RuntimeError 替换。 (更准确地说,这发生在异常即将从生成器的堆栈帧中冒出时。)

例如,这样的循环是否仍然有效?

it = iter([1,2,3])
try:
    i = next(it)
    while True:
        i = next(it)
except StopIteration:
    pass

或者这是否意味着如果我有这样的生成器定义:

def gen():
    yield from range(5)
    raise StopIteration

StopIteration 将被替换为 RuntimeError

如果有人能对此有所了解,我将不胜感激。

【问题讨论】:

    标签: python runtime-error stopiteration


    【解决方案1】:

    您的第一个循环应该仍然可以工作 -- StopIteration 仍会在生成器耗尽时引发。

    不同之处在于,当在生成器中提出StopIteration 时, 存在歧义。它是否被引发(隐式)是因为生成器用完了要让出的东西 - 还是因为委托生成器用完要让出的东西(可能是由于next 调用)并且没有处理异常而被引发适当地? PEP-0479 试图解决这种歧义。现在,如果你得到一个StopIteration,这意味着你正在使用的生成器已经用完了要生成的项目。换句话说,这意味着委托生成器没有在项目用完时被错误处理。

    为支持此更改,您的生成器应return 而不是显式提升StopIteration

    def gen():
        yield from range(5)
        return
    

    如果您在启用StopIterationgenerator_stop 的情况下尝试它会发生什么(这将在python3.7 出现时成为默认设置):

    >>> from __future__ import generator_stop
    >>> def gen():
    ...     yield from range(5)
    ...     raise StopIteration
    ... 
    >>> list(gen())
    Traceback (most recent call last):
      File "<stdin>", line 3, in gen
    StopIteration
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    RuntimeError: generator raised StopIteration
    

    【讨论】:

    • 我明白了。我在阅读StopAsyncIteration 时偶然发现了这一点。现在一切都说得通了。非常感谢。
    猜你喜欢
    • 2017-12-27
    • 2013-12-19
    • 2019-04-02
    • 2021-11-01
    • 2016-08-05
    • 2018-03-26
    • 2019-10-04
    • 1970-01-01
    • 2021-07-30
    相关资源
    最近更新 更多