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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14183803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:41:57  来源:igfitidea点击:

What is the difference between raise StopIteration and a return statement in generators?

pythongeneratorstopiteration

提问by slallum

I'm curious about the difference between using raise StopIterationand a returnstatement in generators.

我很好奇生成器中usingraise StopIterationreturn语句之间的区别。

For example, is there any difference between these two functions?

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

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

I'm guessing the more "pythonic" way to do it is the second way (please correct me if I'm wrong), but as far as I can see both ways raise a StopIterationexception.

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

采纳答案by Jon Clements

There's no need to explicitly raise StopIterationas that's what a bare returnstatement does for a generator function - so yes they're the same. But no, just using returnis more Pythonic.

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

From: http://docs.python.org/2/reference/simple_stmts.html#the-return-statement(valid to Python 3.2)

来自:http: //docs.python.org/2/reference/simple_stmts.html#the-return-statement(对 Python 3.2 有效)

In a generator function, the return statement is not allowed to include an expression_list. In that context, a bare return indicates that the generator is done and will cause StopIteration to be raised.

在生成器函数中,不允许 return 语句包含 expression_list。在这种情况下,裸返回表示生成器已完成并将导致引发 StopIteration。

Or as @Bakuriu points out - the semantics of generators have changed slightly for Python 3.3, so the following is more appropriate:

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

In a generator function, the return statement indicates that the generator is done and will cause StopIteration to be raised. The returned value (if any) is used as an argument to construct StopIteration and becomes the StopIteration.value attribute.

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

回答by Jon Clements

That's true, they are equivalent except that one is readable whereas the other is obscure. This dates back to the very first version of generators (PEP 255, under "Specification: Return"), and the subsequent enhancements of (such as coroutines) do not change this. 3.3's yield from(PEP 380) extends that to return <expr>as syntactic sugar for raise StopIteration(<expr>), but that doesn't change the meaning of return;.

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

回答by Blake Walsh

As of late 2014 returnis correct and raise StopIterationfor ending a generator is on a depreciation schedule. See PEP 479for full details.

截至 2014 年末return是正确的,并且raise StopIteration发电机处于折旧计划中。有关完整详细信息,请参阅PEP 479

Abstract

This PEP proposes a change to generators: when StopIterationis raised inside a generator, it is replaced with RuntimeError. (More precisely, this happens when the exception is about to bubble out of the generator's stack frame.) Because the change is backwards incompatible, the feature is initially introduced using a __future__statement.

Acceptance

This PEP was accepted by the BDFL on November 22…

Rationale

The interaction of generators and StopIteration is currently somewhat surprising, and can conceal obscure bugs. An unexpected exception should not result in subtly altered behaviour, but should cause a noisy and easily-debugged traceback. Currently, StopIteration raised accidentally inside a generator function will be interpreted as the end of the iteration by the loop construct driving the generator.

抽象的

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

验收

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

基本原理

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