【问题标题】:What is the difference between raise StopIteration and a return statement in generators?raise StopIteration 和生成器中的 return 语句有什么区别?
【发布时间】:2012-12-20 11:10:03
【问题描述】:

我很好奇在生成器中使用raise StopIterationreturn 语句之间的区别。

例如,这两个功能有什么区别吗?

def my_generator0(n):
    for i in range(n):
        yield i
        if i >= 5:
            return

def my_generator1(n):
    for i in range(n):
        yield i
        if i >= 5:
            raise StopIteration

我猜测更“pythonic”的方式是第二种方式(如果我错了,请纠正我),但据我所知,两种方式都会引发StopIteration 异常。

【问题讨论】:

  • 显式或隐式('off the end')return 是终止生成器的预期方式。如果 PEP 479 被接受,“raise StopIteration”版本最终将无法像现在这样工作。
  • 请注意,PEP 479 "Change StopIteration handling inside generators" 在 2014 年 11 月被 Python 3.5 接受。

标签: python generator stopiteration


【解决方案1】:

没有必要明确地提出StopIteration,因为这就是一个简单的return 语句对生成器函数所做的事情——所以是的,它们是相同的。但是不,只使用 return 更符合 Python 风格。

来自:http://docs.python.org/2/reference/simple_stmts.html#the-return-statement(适用于 Python 3.2)

在生成器函数中,return 语句不允许包含 expression_list。在这种情况下,一个简单的返回表明生成器已经完成,并将导致 StopIteration 被引发。

或者正如@Bakuriu 指出的那样——Python 3.3 中生成器的语义略有变化,因此以下更合适:

在生成器函数中,return 语句指示生成器已完成并将引发 StopIteration。返回的值(如果有)用作构造 StopIteration 的参数,并成为 StopIteration.value 属性。

【讨论】:

  • 在 python3 中,返回可以有一个表达式列表参数:docs.python.org/3.3/reference/…
  • 注意:如果您在生成器中显式引发 StopIteration 异常,则可能有一些方法(例如 Python 3 的多处理 imap_unordered())会继续出错,因为它们希望收到常规返回(或一个隐式返回)并且将自己提出 StopIteration 。有关基本原理,请参阅@terry-jan-reedy 在stackoverflow.com/questions/14183803/… 中的评论。
【解决方案2】:

截至 2014 年底,return 是正确的,而用于终止发电机的raise StopIteration 处于折旧计划中。详情请参阅PEP 479

摘要

此 PEP 提议对生成器进行更改:当 StopIteration 在生成器内引发时,它会被 RuntimeError 替换。 (更准确地说,当异常即将从生成器的堆栈帧中冒出时会发生这种情况。)由于更改是向后不兼容的,因此最初使用 __future__ 语句引入了该功能。

接受

此 PEP 已于 11 月 22 日被 BDFL 接受...

基本原理

生成器和 StopIteration 的交互目前有点令人惊讶,并且可以隐藏晦涩的错误。意外的异常不应导致行为的细微改变,而应引起嘈杂且易于调试的回溯。目前,在生成器函数中意外引发的 StopIteration 将被驱动生成器的循环构造解释为迭代的结束。

【讨论】:

    【解决方案3】:

    没错,它们是等价的,只是一个可读而另一个晦涩难懂。这可以追溯到生成器的第一个版本(PEP 255,在“规范:返回”下),随后的增强(例如协程)并没有改变这一点。 3.3 的 yield from (PEP 380) 将其扩展到 return <expr> 作为 raise StopIteration(<expr>) 的语法糖,但这不会改变 return; 的含义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-15
      • 2014-05-24
      • 2019-10-04
      • 2011-08-26
      • 2012-06-17
      • 2021-05-15
      • 2015-11-04
      • 1970-01-01
      相关资源
      最近更新 更多