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!
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
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!
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