Single line to check if iterator gives at least one element?

I am currently doing this:

try: something = iterator.next() # ... except StopIteration: # ... 

But I would like to express an expression that I can place inside a simple if . Is there anything inline that will make this code less awkward?

any() returns False if the iterability is empty, but it will potentially iterate over all elements if it is not. I only need to check the first item.




Someone asks what I'm trying to do. I wrote a function that executes an SQL query and gives the results. Sometimes, when I call this function, I just want to know if the request returned something and made a decision based on this.

+58
python iterator
Jun 24 2018-10-06T00:
source share
7 answers

any will not exceed the first element if it is True. If the iterator gives something false, you can write any(True for _ in iterator) .

+100
Jun 24 '10 at 23:28
source share

In Python 2.6+, if the name sentinel bound to a value that the iterator cannot execute,

 if next(iterator, sentinel) is sentinel: print('iterator was empty') 

If you do not know that the iterator can give way, make your own watchdog (for example, at the top of your module) with

 sentinel = object() 

Otherwise, you can use as a gatekeeper any value that you β€œknow” (based on application considerations) that the iterator cannot give.

+31
Jun 24 '10 at 23:12
source share

This is not very clean, but it shows a way to batch convert to a lossless function:

 def has_elements(iter): from itertools import tee iter, any_check = tee(iter) try: any_check.next() return True, iter except StopIteration: return False, iter has_el, iter = has_elements(iter) if has_el: # not empty 

This is not really pythonic, and for some cases there are probably better (but less general) solutions, such as next by default.

 first = next(iter, None) if first: # Do something 

This is not common, because None can be a valid element in many iterations.

+18
Jun 24 2018-10-10T00:
source share

you can use:

 if zip([None], iterator): # ... else: # ... 

but it is a little inefficient for the code reader

+5
Jun 24 2018-10-06T00:
source share

__length_hint__ evaluates the length of list(it) - this is a private method:

 x = iter( (1, 2, 3) ) help(x.__length_hint__) 1 Help on built-in function __length_hint__: 2 3 __length_hint__(...) 4 Private method returning an estimate of len(list(it)). 
0
Jun 24 '10 at 22:12
source share

This is the overkill iterator shell, which usually allows you to check if the next element is there (via conversion to logical). Of course, quite inefficient.

 class LookaheadIterator (): def __init__(self, iterator): self.__iterator = iterator try: self.__next = next (iterator) self.__have_next = True except StopIteration: self.__have_next = False def __iter__(self): return self def next (self): if self.__have_next: result = self.__next try: self.__next = next (self.__iterator) self.__have_next = True except StopIteration: self.__have_next = False return result else: raise StopIteration def __nonzero__(self): return self.__have_next x = LookaheadIterator (iter ([])) print bool (x) print list (x) x = LookaheadIterator (iter ([1, 2, 3])) print bool (x) print list (x) 

Output:

 False [] True [1, 2, 3] 
0
Jun 24 '10 at 23:09
source share

A little late, but ... You can include an iterator in a list, and then work with this list:

 # Create a list of objects but runs out the iterator. 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 (ie from the iterator) else : pass # Iterator was empty, thus list is empty. 
0
Feb 05 '15 at 22:28
source share



All Articles