python 的生成器函数中引发的 StopIteration 异常处理
StopIteration exception handling raised in generator function in python
这是我的生成器函数代码:
def fibo():
n1=0
n2=1
while True:
if n1 == 8:
raise StopIteration
else:
yield n1
n1,n2=n2,n1+n2
seq=fibo()
这是我用于生成序列的代码版本 1:
for ele in seq:
print(next(seq))
输出:
1
2
5
RuntimeError: generator raised StopIteration
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-3-c01815b93e23> in fibo()
5 if n1 == 8:
----> 6 raise StopIteration
7 else:
StopIteration:
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
<ipython-input-3-c01815b93e23> in <module>
11 seq=fibo()
12
---> 13 for ele in seq:
14 print(next(seq))
15
RuntimeError: generator raised StopIteration
版本 1 的预期输出:
0
1
1
2
3
5
这是我用于生成序列的代码版本 2:
while True:
try:
print(next(seq))
except StopIteration:
print('This exception is raised in the generator operation defining function. Hence it is handled here.')
break
输出:
0
1
1
2
3
5
RuntimeError: generator raised StopIteration
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-4-6afe26583a33> in fibo()
5 if n1 == 8:
----> 6 raise StopIteration
7 else:
StopIteration:
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
<ipython-input-4-6afe26583a33> in <module>
16 while True:
17 try:
---> 18 print(next(seq))
19 except StopIteration:
20 print('This exception is raised in the generator operation defining function. Hence it is handled here.')
RuntimeError: generator raised StopIteration
版本 2 的预期输出:
0
1
1
2
3
5
This exception is raised in the generator operation defining function. Hence it is handled here.
第一个版本out不正确,出现异常。在第二个中,除了正确的输出之外,还发生了与版本 1 相同的异常。
请帮我纠正一下。
不用引发异常,只需使用 return
即可
if n1 == 8:
return
当您的生成器产生 StopIteration
错误时,实际程序收到 RuntimeError
。以下将起作用:
seq=fibo()
while True:
try:
print(next(seq))
except RuntimeError:
print('This exception is raised in the generator operation defining function. Hence it is handled here.')
break
Here is my code version-1 for generating sequence:
Python 中的 for
循环构造的要点是 已经 调用 next
在迭代器上(它从生成器自动创建)。所以你应该 print(ele)
代替。
RuntimeError: generator raised StopIteration
是的,因为您不应该在生成器中使用显式 raise StopIteration
。这是一个 old 工具,用于向 for
循环传达您没有元素的信息,仅当您实现 __iter__
老式方法时才需要方法。是的,for
循环构造依赖于这个异常来确定输入的结束;但是从您的生成器创建的迭代器将自动执行此操作 - 并且还会检查生成器中引发的 StopIteration
s 并将它们转换为 RuntimeError
,明确地 prevent 您的StopIteration
摆脱循环。
如果底层机器没有那个检查,那么你可以做类似 for i in itertools.chain(my_generator, a_list):
的事情,并且生成器实现引发的异常会 强行中断 循环(毕竟,循环通过 处理该异常 退出)并防止 a_list
元素被看到。这不是您希望生成器的行为方式,并且在某种意义上它也是一种安全风险,因此存在检查。
如果你想发信号通知生成器已完成 yield
ing,你要做的是......到达代码的末尾。例如,使用 return
,或者在这种情况下 break
也有效(因为循环后没有其他内容):
def fibo():
n1, n2 = 0, 1
while True:
if n1 == 8:
break
else:
yield n1
n1, n2 = n2, n1+n2
print('This exception is raised in the generator operation defining function. Hence it is handled here.')
没有发生的原因是您正在尝试捕获 StopIteration
(您 不应该这样做 因为它会干扰循环的操作!) ,但例外是(如果您仔细阅读堆栈跟踪,您会知道)替换为 RuntimeError
。见上文。
使用上面更正的代码,一切都按预期工作:
>>> list(fibo())
[0, 1, 1, 2, 3, 5]
>>> x = fibo()
>>> for f in x:
... print(f)
...
0
1
1
2
3
5
>>> x = fibo()
>>> while True:
... try:
... print(next(x))
... except StopIteration:
... print('this works as intended - but a for loop is much cleaner')
... break
...
0
1
1
2
3
5
this works as intended - but a for loop is much cleaner
这是我的生成器函数代码:
def fibo():
n1=0
n2=1
while True:
if n1 == 8:
raise StopIteration
else:
yield n1
n1,n2=n2,n1+n2
seq=fibo()
这是我用于生成序列的代码版本 1:
for ele in seq:
print(next(seq))
输出:
1
2
5
RuntimeError: generator raised StopIteration
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-3-c01815b93e23> in fibo()
5 if n1 == 8:
----> 6 raise StopIteration
7 else:
StopIteration:
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
<ipython-input-3-c01815b93e23> in <module>
11 seq=fibo()
12
---> 13 for ele in seq:
14 print(next(seq))
15
RuntimeError: generator raised StopIteration
版本 1 的预期输出:
0
1
1
2
3
5
这是我用于生成序列的代码版本 2:
while True:
try:
print(next(seq))
except StopIteration:
print('This exception is raised in the generator operation defining function. Hence it is handled here.')
break
输出:
0
1
1
2
3
5
RuntimeError: generator raised StopIteration
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-4-6afe26583a33> in fibo()
5 if n1 == 8:
----> 6 raise StopIteration
7 else:
StopIteration:
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
<ipython-input-4-6afe26583a33> in <module>
16 while True:
17 try:
---> 18 print(next(seq))
19 except StopIteration:
20 print('This exception is raised in the generator operation defining function. Hence it is handled here.')
RuntimeError: generator raised StopIteration
版本 2 的预期输出:
0
1
1
2
3
5
This exception is raised in the generator operation defining function. Hence it is handled here.
第一个版本out不正确,出现异常。在第二个中,除了正确的输出之外,还发生了与版本 1 相同的异常。 请帮我纠正一下。
不用引发异常,只需使用 return
即可
if n1 == 8:
return
当您的生成器产生 StopIteration
错误时,实际程序收到 RuntimeError
。以下将起作用:
seq=fibo()
while True:
try:
print(next(seq))
except RuntimeError:
print('This exception is raised in the generator operation defining function. Hence it is handled here.')
break
Here is my code version-1 for generating sequence:
Python 中的 for
循环构造的要点是 已经 调用 next
在迭代器上(它从生成器自动创建)。所以你应该 print(ele)
代替。
RuntimeError: generator raised StopIteration
是的,因为您不应该在生成器中使用显式 raise StopIteration
。这是一个 old 工具,用于向 for
循环传达您没有元素的信息,仅当您实现 __iter__
老式方法时才需要方法。是的,for
循环构造依赖于这个异常来确定输入的结束;但是从您的生成器创建的迭代器将自动执行此操作 - 并且还会检查生成器中引发的 StopIteration
s 并将它们转换为 RuntimeError
,明确地 prevent 您的StopIteration
摆脱循环。
如果底层机器没有那个检查,那么你可以做类似 for i in itertools.chain(my_generator, a_list):
的事情,并且生成器实现引发的异常会 强行中断 循环(毕竟,循环通过 处理该异常 退出)并防止 a_list
元素被看到。这不是您希望生成器的行为方式,并且在某种意义上它也是一种安全风险,因此存在检查。
如果你想发信号通知生成器已完成 yield
ing,你要做的是......到达代码的末尾。例如,使用 return
,或者在这种情况下 break
也有效(因为循环后没有其他内容):
def fibo():
n1, n2 = 0, 1
while True:
if n1 == 8:
break
else:
yield n1
n1, n2 = n2, n1+n2
print('This exception is raised in the generator operation defining function. Hence it is handled here.')
没有发生的原因是您正在尝试捕获 StopIteration
(您 不应该这样做 因为它会干扰循环的操作!) ,但例外是(如果您仔细阅读堆栈跟踪,您会知道)替换为 RuntimeError
。见上文。
使用上面更正的代码,一切都按预期工作:
>>> list(fibo())
[0, 1, 1, 2, 3, 5]
>>> x = fibo()
>>> for f in x:
... print(f)
...
0
1
1
2
3
5
>>> x = fibo()
>>> while True:
... try:
... print(next(x))
... except StopIteration:
... print('this works as intended - but a for loop is much cleaner')
... break
...
0
1
1
2
3
5
this works as intended - but a for loop is much cleaner