在 python 中的生成器函数中引发的 StopIteration 异常处理

圣沙兰

这是我的生成器函数代码:

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 相同的异常。请帮我纠正这个问题。

卡尔·克内克特尔

这是我用于生成序列的代码版本 1:

forPython中循环结构是,它已经呼吁next在迭代器(它从自动生成器创建)。所以你应该只是print(ele)相反。

运行时错误:生成器引发了 StopIteration

是的,因为您不应该raise StopIteration在生成器中使用显式这是一个旧的工具,用于向for循环传达您已用完元素的信息,只有在您以__iter__老式方式实现方法时才需要这种工具。是的,for循环构造依赖于这个异常来确定输入的结束;但是从您的生成器创建的迭代器会自动执行此操作 - 并且还会检查StopIteration生成器中是否存在s 并将它们转换为RuntimeError, 以防止StopIteration跳出循环。

如果底层机器没有那个检查,那么你可以做这样的事情for i in itertools.chain(my_generator, a_list):,并且生成器实现引发的异常将强行中断循环(毕竟,循环通过处理该异常退出)并防止a_list元素被看到. 这不是您希望生成器的行为方式,并且在某种意义上也是一种安全风险,因此该检查就在那里。

如果你想发出一个生成器已经完成的信号,yield你要做的是......到达代码的末尾。例如, with return, or 在这种情况下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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章