提升StopIteration和生成器中的return语句有什么区别?

时间:2013-01-06 15:52:11

标签: python generator stopiteration

我很好奇在生成器中使用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异常。 / p>

3 个答案:

答案 0 :(得分:39)

没有必要明确地提出StopIteration,因为这是一个裸return语句对生成器函数的作用 - 所以是的,它们是相同的。但不,只是使用return更像是Pythonic。

来自: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属性。

答案 1 :(得分:17)

截至2014年底return是正确的,结束生成器的raise StopIteration是折旧计划。有关详细信息,请参阅PEP 479

  

摘要

     

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

     

接受

     

该PEP于11月22日被BDFL接受......

     

原理

     

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

     

...

答案 2 :(得分:3)

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