[Python-ideas] "Iteration stopping" syntax [Was: Is this PEP-able? for X in ListY while conditionZ:]

Nick Coghlan ncoghlan at gmail.com
Mon Jul 1 03:30:30 CEST 2013


On 1 July 2013 10:59, Steven D'Aprano <steve at pearwood.info> wrote:
> So I think the missing piece is that generators are actually iterators.
> Since raising StopIteration is the official way to halt an iterator, it's
> also the (or at least, an) official way to halt a generator, and not a quirk
> of the implementation.

Yeah, the reason Andrew's proposed fix to the comprehension semantics
makes sense is the fact that exactly *where* StopIteration gets raised
during a "__next__" invocation is supposed to be completely opaque
from the point of view of the iterator protocol:

    while True:
        try:
            x = next(itr):
        except StopIteration:
            break
        # Process x...

The caught "StopIteration" could come from:

- a generator iterator frame terminating
- a generator iterator explicitly raising StopIteration
- a sequence iterator triggering IndexError
- a sentinel iterator noticing the sentinel value
- any other __next__ method raising StopIteration

When I did the conversion to "make [x for x in y] merely an optimised
version of list(x for x in y)" change for Python 3, I know I missed
the fact that part of that change involved moving the evaluation of
all of the subexpressions inside the implicit try/except that is part
of the iterator protocol, and I don't recall anyone else bringing it
up either. Even if it did come up, we must have dismissed it as
introducing too much overhead to set up the
almost-certainly-unnecessary try/except for each iteration.
Fortunately, Andrew is right that we can avoid that overhead and use a
single try/except to cover the whole comprehension, which is a nice
and cheap change.

Cheers,
Nick.


More information about the Python-ideas mailing list