On Fri, 01 Apr 2005 16:34:32 GMT, "Raymond Hettinger" <[EMAIL PROTECTED]> wrote:
>[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 > > I assumed that all standard sequence consumers (including list, of course) would intercept the StopIteration of a sequence given them in the form of a generator expression, so your lyst example would have an analogue for other sequence consumers as well, right? I.e., there's not a hidden list(genex) in those others I would hope ;-) E.g., "in" in my toy exposed more clearly, using Peter's stop: >>> def show(x): print x,; return x ... >>> def stop(): raise StopIteration ... >>> 2 in (x for x in xrange(5) if show(x)<4 or stop()) 0 1 2 True >>> 7 in (x for x in xrange(5) if show(x)<4 or stop()) 0 1 2 3 4 False BTW I notice that this also nicely shortcuts when the 2 is found. Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list