I have a list of generators in a function alternate_all(*args)
that alternates between each generator in the list to print their first item, second item, ..., etc. until all generators are exhausted.
My code works until a generator is exhausted and once the StopIteration occurs, it stops printing, when I want it to continue with the rest of the generators and ignore the exhausted one:
def alternate_all(*args):
iter_list = []
for iterable in args:
iter_list.append(iter(iterable))
try:
while True:
for iterable in iter_list:
val = next(iter_list[0])
iter_list.append(iter_list.pop(0))
yield val
except StopIteration:
pass
if __name__ == '__main__':
for i in alternate_all('abcde','fg','hijk'):
print(i,end='')
My output is:
afhbgic
When it should be:
afhbgicjdke
How can I get this to ignore the exhausted generator? I would prefer not to use itertools and keep this same structure.
This works. I tried to stay close to how your original code works (though I did replace your first loop with a list comprehension for simplicity).
def alternate_all(*args):
iter_list = [iter(arg) for arg in args]
while iter_list:
i = iter_list.pop(0)
try:
val = next(i)
except StopIteration:
pass
else:
yield val
iter_list.append(i)
The main problem with your code was that your try
/except
was outside of the loop, meaning the first exhausted iterator would exit from the loop. Instead, you want to catch StopIteration
inside the loop so you can keep going, and the loop should keep going while iter_list
still has any iterators in it.