Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 673
Brooks Moses Avatar asked Jan 10 '13 03:01

Brooks Moses


People also ask

How do I check if a Python iterator is empty?

l = [_ for _ in iterator] # If the list is not empty then the iterator had elements; else it was empty. if l : pass # Use the elements of the list (i.e. from the iterator) else : pass # Iterator was empty, thus list is empty.

What does next () do in Python?

The next() function returns the next item in an iterator. You can add a default return value, to return if the iterable has reached to its end.

Which functions return an iterable with a next () method that yields the next element in a sequence?

The __iter__() method returns the iterator object itself. If required, some initialization can be performed. The __next__() method must return the next item in the sequence. On reaching the end, and in subsequent calls, it must raise StopIteration .

What does __ ITER __ do in Python?

The __iter__() function returns an iterator for the given object (array, set, tuple, etc. or custom objects). It creates an object that can be accessed one element at a time using __next__() function, which generally comes in handy when dealing with loops.


1 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 
like image 136
DSM Avatar answered Oct 07 '22 16:10

DSM