首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >何时将StopIteration转换为RuntimeError?

何时将StopIteration转换为RuntimeError?
EN

Stack Overflow用户
提问于 2018-08-06 16:32:50
回答 1查看 3.8K关注 0票数 10

我正在阅读Python3 这里的文档

如果生成器代码直接或间接引发StopIteration,则将其转换为RuntimeError (保留StopIteration作为新异常的原因)。

我不明白,有人能解释一下吗?

这是我在Python3.6中尝试过的,但似乎没有发现:

代码语言:javascript
复制
def gen1():
    yield from [1, 2, 3]
    raise StopIteration

def gen2():
    raise StopIteration

try:
    a = list(gen1())
    # a == [1, 2, 3]
except RuntimeError:
    print("Caught")

try:
    a = gen1()
    next(a), next(a), next(a), next(a), next(a)
except RuntimeError:
    print("Caught")

try:
    gen2()
except RuntimeError:
    print("Caught")

try:
    a = list(gen2())
except RuntimeError:
    print("Caught")

特别是,对gen2()的两个调用都会引发StopIteration,但仍未转换为RuntimeError

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-06 16:35:38

您忽略了这个更改适用于Python3.7和更高版本。您将不会看到Python3.6或更高版本中的转换,除非您首先使用from __future__导入启用该特性(在Python3.5中可用)。

从您链接的同一页:

在3.5版中更改:通过RuntimeError引入了from __future__ import generator_stop转换,参见PEP 479。 在版本3.7中更改:默认情况下为所有代码启用PEP 479 :在生成器中引发的StopIteration错误将转换为RuntimeError

佩普479 --进一步详细介绍了做出此更改的原因及其应用方式。对于运行在Python3.7上的代码,输出如下:

代码语言:javascript
复制
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=7, micro=0, releaselevel='final', serial=0)
>>> def gen1():
...     yield from [1, 2, 3]
...     raise StopIteration
...
>>> def gen2():
...     yield 42  # make this an actual generator
...     raise StopIteration
...
>>> try:
...     a = list(gen1())
... except RuntimeError:
...     print("Caught")
...
Caught
>>> try:
...     a = gen1()
...     next(a), next(a), next(a), next(a), next(a)
... except RuntimeError:
...     print("Caught")
...
Caught
>>> try:
...     a = list(gen2())
... except RuntimeError:
...     print("Caught")
...
Caught

请注意,我向yield 42添加了一个gen2()行,使其成为一个生成器。如果体内没有yieldyield from,则会得到一个常规函数。调用生成器函数将生成生成器对象,函数体开始暂停,而调用普通函数则立即执行主体:

代码语言:javascript
复制
>>> def normal():
...     raise StopIteration
...
>>> def generator():
...     raise StopIteration
...     yield  # never reached, but this is now a generator
...
>>> normal()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in normal
StopIteration
>>> generator()
<generator object generator at 0x105831ed0>
>>> next(generator())
Traceback (most recent call last):
  File "<stdin>", line 2, in generator
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

对于Python3.6,您可以使用from __future__ import generator_stop编译器开关(在编写脚本或模块时在代码顶部使用它):

代码语言:javascript
复制
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=6, micro=5, releaselevel='final', serial=0)
>>> def generator():
...     raise StopIteration
...     yield
...
>>> next(generator())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in generator
StopIteration
>>> from __future__ import generator_stop
>>> def generator():  # re-define it so it is compiled anew
...     raise StopIteration
...     yield
...
>>> next(generator())
Traceback (most recent call last):
  File "<stdin>", line 2, in generator
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
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51712065

复制
相关文章

相似问题

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