StopIteration in the if clause of a generator expression

Raymond Hettinger vze4rx4y at verizon.net
Fri Apr 1 11:34:32 EST 2005


[Peter Otten]
> a StopIteration raised in a generator expression
> silently terminates that generator:
>
> >>> def stop(): raise StopIteration
> ...
> >>> list(i for i in range(10) if i < 5 or stop())
> [0, 1, 2, 3, 4]
>
> In a list comprehension, on the other hand, it is propagated:
>
> >>> [i for i in range(10) if i < 5 or stop()]
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>   File "<stdin>", line 1, in stop
> StopIteration
>
> Is that an intentional difference?

I would call it an unfortunate assymmetry -- one the never comes up unless
you're up to no good ;-)

In a way, both behave identically.  They both raise StopIteration.  In the case
of the generator expression, that StopIteration is intercepted by the enclosing
list() call.  That becomes obvious if you write a pure python equivalent for
list:

    def lyst(s):
        it = iter(s)
        result = []
        try:
            while 1:
                result.append(it.next())
        except StopIteration:        # guess who trapped StopIter
            return result


Raymond Hettinger






More information about the Python-list mailing list