How do I know if a generator is empty from the start?
Solution 1:
Suggestion:
def peek(iterable):
try:
first = next(iterable)
except StopIteration:
return None
return first, itertools.chain([first], iterable)
Usage:
res = peek(mysequence)
if res is None:
# sequence is empty. Do stuff.
else:
first, mysequence = res
# Do something with first, maybe?
# Then iterate over the sequence:
for element in mysequence:
# etc.
Solution 2:
The simple answer to your question: no, there is no simple way. There are a whole lot of work-arounds.
There really shouldn't be a simple way, because of what generators are: a way to output a sequence of values without holding the sequence in memory. So there's no backward traversal.
You could write a has_next function or maybe even slap it on to a generator as a method with a fancy decorator if you wanted to.
Solution 3:
A simple way is to use the optional parameter for next() which is used if the generator is exhausted (or empty). For example:
_exhausted = object()
if next(some_generator, _exhausted) is _exhausted:
print('generator is empty')
Solution 4:
next(generator, None) is not None
Or replace None
but whatever value you know it's not in your generator.
Edit: Yes, this will skip 1 item in the generator. Often, however, I check whether a generator is empty only for validation purposes, then don't really use it. Or otherwise I do something like:
def foo(self):
if next(self.my_generator(), None) is None:
raise Exception("Not initiated")
for x in self.my_generator():
...
That is, this works if your generator comes from a function, as in generator()
.