Python PEP479:更改生成器内 StopIteration 的处理方式

11

有人可以帮助我理解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

如果有人能够解释一下这件事情,我会非常感激。

1个回答

15

你的第一个循环应该仍然有效 - 当生成器用尽时,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的内容时偶然发现了这个问题。现在一切都清楚了。非常感谢。 - Jacques Gaudin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接