On Wed, 30 Dec 2009 15:18:11 -0800, Tom Machinski wrote: > Thanks for the comment and discussion guys. > > Bottom line, I'm going to have to remove this pattern from my code: > > foo = (foo for foo in foos if foo.bar).next()
I don't see why. What's wrong with it? Unless you embed it in a call to list, or similar, it will explicitly raise StopIteration as expected. > I used to have that a lot in cases where not finding at least one valid > foo is an actual fatal error. What's wrong with the obvious solution? if not any(foo for foo in foos if foo.bar): raise ValueError('need at least one valid foo') > But using StopIteration to signal a fatal > condition becomes a bug when interacting with list() as shown in the > original post. You shouldn't use StopIteration to signal fatal conditions, because that's not what it is for. It's acceptable to catch it when *directly* calling next, but otherwise you should expect that StopIteration will be caught and suppressed by just about anything. > It would be nice if there was a builtin for "get the first element in a > genexp, or raise an exception (which isn't StopIteration)", Not everything needs to be a built-in. def get_first_or_fail(iterable_or_sequence): it = iter(iterable_or_sequence) try: return it.next() # use next(it) in Python 3 except StopIteration: raise ValueError('empty iterable') This is perfectly usable as a helper function, or it's short enough to be used in-line if you prefer. -- Steven -- http://mail.python.org/mailman/listinfo/python-list