Python Forum

Full Version: testing if an iterator is empty
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
is there a way to test if an iterator is empty without "consuming" any content in case it is not empty? does a true/false test accomplish this? i don't want to iterate them to a list because some may be too large or infinite.
When an iterator is empty it should return aStopIteration
You can use more_itertools.peekable() to simulate this. Testing truth value on a peekable tells whether it is empty
>>> import more_itertools as mit
>>> import io
>>> f = io.StringIO("""\
... Hello
... World
... !!!""")
>>> z = mit.peekable(f)
>>> z.peek()
'Hello\n'
>>> z.peek()
'Hello\n'
>>> bool(z)
True  # z is not exhausted
>>> for line in z:
...     print(line)
... 
Hello

World

!!!
>>> bool(z) # z is exhausted
False
However, internally, the first time you call peek(), the inner iterator f is advanced. It is impossible to determine if a general iterator is empty without trying to advance it.
(Feb-23-2022, 12:59 AM)BashBedlam Wrote: [ -> ]When an iterator is empty it should return aStopIteration

what happens if it is not empty?
so the short answer to "is there a way ... ?" is "no".
Would it help to roll you own iterator?
class My_Personal_Iterator :
	def __init__ (self, maximum) :
		self.maximum = maximum
		self.output_number = 0

	def __iter__ (self) :
		return self

	def check_iterator (self) :
		return self.maximum - self.output_number

	def __next__ (self) :
		self.output_number += 1
		if self.output_number <= self.maximum :
			return self.output_number
		else :
			return StopIteration

tester = My_Personal_Iterator (7)
print (next (tester))
print (next (tester))
print (next (tester))
iterations_left = tester.check_iterator ()
print (f'There are {iterations_left} iterations left.')
print (next (tester))
print (next (tester))
print (next (tester))
print (next (tester))
iterations_left = tester.check_iterator ()
print (f'There are {iterations_left} iterations left.')
print (next (tester))
Output:
1 2 3 There are 4 iterations left. 4 5 6 7 There are 0 iterations left. <class 'StopIteration'>
(Feb-24-2022, 09:21 PM)BashBedlam Wrote: [ -> ]Would it help to roll you own iterator?

no. this needs to work with whatever iterator it gets.
(Feb-24-2022, 08:23 PM)Skaperen Wrote: [ -> ]so the short answer to "is there a way ... ?" is "no".
Skaperen Wrote:this needs to work with whatever iterator it gets.
You want something that is structurally impossible. Consider the following iterator
def user_inputs():
    while True:
        yield input("Give me a string: ")

iterator = user_inputs()
Now 'iterator' is empty iff the user decides not to type the Enter key until the program exits. There is no way for the program to read the user's mind. Even if the program calls next(iterator), the answer will be known only if this call returns before the program exits.
the code i was going to use this for gets an object passed via a method argument. it tests to see if it is an iterator using isinstance(the_arg,collections.abc.Iterator) then it would be nice to know if it is empty. but this is not essential to know. it could just handle things better, i'll still do the if not test in case i's an empty sequence.