Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm curious about the difference between using raise StopIteration and a return statement in generators.

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 StopIteration exception.

like image 490
slallum Avatar asked Jan 06 '13 15:01

slallum


People also ask

What is the purpose of the return statement in a generator?

A return statement in a generator, when executed, will make the generator finish (i.e. the done property of the object returned by it will be set to true ). If a value is returned, it will be set as the value property of the object returned by the generator.

How do you raise a StopIteration?

Iterator in Python uses the two methods, i.e. iter() and next(). The next() method raises an StopIteration exception when the next() method is called manually. The best way to avoid this exception in Python is to use normal looping or use it as a normal iterator instead of writing the next() method again and again.

What does a generator return what does a generator return?

Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).

What is StopIteration error in Python?

In Python, StopIteration is an exception which occurred by built-in next() and __next__() method in iterator to signal that iteration is done for all items and no more to left to iterate.


2 Answers

There's no need to explicitly raise StopIteration as that's what a bare return statement does for a generator function - so yes they're the same. But no, just using return is more Pythonic.

From: http://docs.python.org/2/reference/simple_stmts.html#the-return-statement (valid to 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.

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

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.

like image 133
Jon Clements Avatar answered Oct 09 '22 11:10

Jon Clements


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

Abstract

This PEP proposes a change to generators: when StopIteration is 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.

like image 33
Blake Walsh Avatar answered Oct 09 '22 10:10

Blake Walsh