On Sat, Sep 20, 2008 at 10:06 PM, Carl Johnson firstname.lastname@example.org wrote:
An alternate construct could be something like:
""" def While(x): if x > 10: return None else: return x
[w for w in (While(x) for x in range(20)) if w is not None] """
The problem is that this version won't work if range(20) is replaced with itertools.count() or any other non-finite generator, whereas the raise Break version will.
Another nice thing about using raise for loop control is that "raise Continue" can be used to skip elements:
def even(x): if x % 2: raise Continue else: return x
[even(x) for x in range(10)] # [0, 2, 4, 6, 8]
This would have to be broken in two parts to do in current Python (and indeed, that might be the chief advantage of *not* adopting my proposal--TOOWTDI):
def foo(): for x in range(10): if even(x): print "Even!" else: print "Odd!"
I would never expect a function could raise an exception which is silently swallowed up. Having break be a statement enforces locality, a good thing IMO.
generator expressions may currently swallow up StopIteration, but I argue this is a bug. It may not be worth fixing, but it's a bug nonetheless.
The sweet spot for list-comps and generator expressions is when they're *simple*. Once they start to get complicated or fancy (such as making them exit early) you should switch to an explicit for-statement; more lines really is more readable.