Default value for next element in Python iterator if iterator is empty?

Question:

I have a list of objects, and I would like to find the first one for which a given method returns true for some input value. This is relatively easy to do in Python:

pattern = next(p for p in pattern_list if p.method(input))

However, in my application it is common that there is no such p for which p.method(input) is true, and so this will raise a StopIteration exception. Is there an idiomatic way to handle this without writing a try/catch block?

In particular, it seems like it would be cleaner to handle that case with something like an if pattern is not None conditional, so I’m wondering if there’s a way to expand my definition of pattern to provide a None value when the iterator is empty — or if there’s a more Pythonic way to handle the overall problem!

Asked By: Brooks Moses

||

Answers:

next accepts a default value:

next(...)
    next(iterator[, default])

    Return the next item from the iterator. If default is given and the iterator
    is exhausted, it is returned instead of raising StopIteration.

and so

>>> print next(i for i in range(10) if i**2 == 9)
3
>>> print next(i for i in range(10) if i**2 == 17)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> print next((i for i in range(10) if i**2 == 17), None)
None

Note that you have to wrap the genexp in the extra parentheses for syntactic reasons, otherwise:

>>> print next(i for i in range(10) if i**2 == 17, None)
  File "<stdin>", line 1
SyntaxError: Generator expression must be parenthesized if not sole argument
Answered By: DSM
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.