iBu*_*Bug 5 python runtime-error generator python-3.x stopiteration
我读的Python 3文档在这里:
如果生成器代码直接或间接引发
StopIteration,则将其转换为RuntimeError(保留StopIteration作为新异常的原因).
我不明白,有谁能解释一下?
这是我在Python 3.6中尝试过的,但似乎没有抓到:
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")
Run Code Online (Sandbox Code Playgroud)
特别是,两次调用都gen2()提升了StopIteration,但仍未转换成RuntimeError.
您错过了此更改适用于Python 3.7及更高版本.您不会在Python 3.6或更早版本中看到转换,除非您from __future__首先使用导入启用该功能(从Python 3.5开始提供).
从您链接的同一页面:
版本3.5中已更改:引入了
RuntimeError转换from __future__ import generator_stop,请参阅PEP 479.在3.7版中更改:默认情况下为所有代码启用PEP 479:
StopIteration生成器中引发的错误转换为aRuntimeError.
PEP 479 - 更改生成器内部的StopIteration处理进一步详细说明了为何进行此更改以及如何应用此更改.对于在Python 3.7上运行的代码,输出变为:
>>> 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
Run Code Online (Sandbox Code Playgroud)
请注意,我添加了yield 42一行gen2()以使其成为生成器.没有yield或yield from在身体中,你会得到一个常规的功能.调用生成器函数会生成一个生成器对象,并且函数体开始暂停,而调用普通函数会立即执行正文:
>>> 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
Run Code Online (Sandbox Code Playgroud)
对于Python 3.6,您将使用from __future__ import generator_stop编译器开关(在编写脚本或模块时在代码顶部使用它):
>>> 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
915 次 |
| 最近记录: |