[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