pythongenerator

StopIterator seemingly raised prematurely by generator in nested for loop


I expected the above generator to produce at least 16 values but for reasons beyond me a StopIterator is raised at the end of the innermost for loop.

What am I doing wrong?

>>> def generator():
...     counter = 0
...     upper_index = [0, 1, 2, 3, 7, 6, 5 , 4]
...     lower_index = reversed(upper_index )
...     for i in range(4):
...         for _ in range(2):
...             for up, down in zip(upper_index , lower_index):
...                 yield (up, down, counter)
...                 counter += 1
...
>>>
>>>
>>> gen = generator()
>>> for _ in range(16):
...     print(next(gen))
...
(0, 4, 0)
(1, 5, 1)
(2, 6, 2)
(3, 7, 3)
(7, 3, 4)
(6, 2, 5)
(5, 1, 6)
(4, 0, 7)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
StopIterator

Solution

  • reversed returns an iterator, not a list, so once that iterator has been iterated once, it's exhausted (empty). That means that that zip iterator will also be empty as a result.

    To allow lower_index to be iterated multiple times, I would instead make it a list using either of these ways:

    lower_index = list(reversed(upper_index))
    
    # or
    
    lower_index = upper_index[::-1]