[Python-ideas] Change how Generator Expressions handle StopIteration

Terry Reedy tjreedy at udel.edu
Sat Nov 8 01:53:04 CET 2014


On 11/7/2014 12:10 PM, Guido van Rossum wrote:

> We'd still need to specify the eventual behavior. I propose the
> following as a strawman (after the deprecation period is finished and
> the __future__ import is no longer needed):

Double meanings are a constant problem.  The ambiguity of StopIteration 
(unintended bug indicator? intended stop signal?) is not needed within 
generator functions*.  An explicit 'raise StopIteration' is more easily 
written 'return'.  The rare. clever, 'yield expression' that means 
'either yield the value of expression or raise StopIteration' can be 
re-written

try:
    tem = expression
except StopIteration:
    return
yield tem

An anonymous generator expression with a 'yield or raise' expresssion 
can be re-written as a named generator function. In this context, 
allowing 'yield or raise' is too clever in that it breaks the desired 
(intended?) equivalence between 'list(genexp)' and '[genexp]'.  I agree 
that this is a bad tradeoff.

Such alternative could be documented.

* StopIteration raised within a __next__ method could be a bug, but a) 
this should be rare, b) the possibility cannot be eliminated, and c) it 
would be too expensive to not take StopIteration at face value.

> - If a StopIteration is about to bubble out of a generator frame, it is
> replaced with some other exception (maybe RuntimeError,

I support this particular replacement.  To me:
1. The proposal amounts to defining StopIteration escaping a running 
generator frame as a runtime error.

 > maybe a new custom Exception subclass,
 > but *not* deriving from StopIteration)

2. There are already more Exception classes than I can remember.
3. This error should be very rare after the transition.
4. A good error message will be at least as important as the class name.
5. A new, specific exception class is an invitation for people to write 
code that raises StopIteration so that its replacement can be caught in 
an except clause in the calling code.  If the existing builtin 
exceptions other than StopIteration are not enough to choose from, one 
can define a custom class.

 > which  causes the next() call (which invoked the generator) to fail,
 > passing that exception out.
> From then on it's just like any old exception.

Any replacement will be ordinary as soon as it is made, before it 
reaches next(), so I would move this last line up a couple of lines.

-- 
Terry Jan Reedy



More information about the Python-ideas mailing list