pythonloopsfor-loopiteratorgenerator

Python generator missing a value during iteration


Hello while using generators in my code, I noticed this strange behaviour where after breaking out from the loop, the next() call on a generator skips one value. Example code:

from itertools import cycle

def endless():
    yield from cycle((9,8,7,6))

total=0
e = endless()
for i in e:
    if total<30:
        total += i
        print(i, end=" ")
    else:
        print()
        print("Reached the goal!")
        break

print(next(e), next(e), next(e))

This outputs:

9 8 7 6 
Reached the goal!
8 7 6

Why does it skip printing 9 after breaking out from the loop. I was expecting it to print the following instead:

9 8 7 6 
Reached the goal!
9 8 7

Solution

  • The missing 9 is the value of i on the last loop iteration. On that iteration, i is 9, but the loop exits without printing it. The next value is then 8.

    You can fix it by always printing the current value within the loop:

    #!/usr/bin/python3
    
    from itertools import cycle
    
    def endless():
        yield from cycle((9,8,7,6))
    
    total=0
    e = endless()
    for i in e:
        total += i
        print(i, end=" ")
    
        if total >= 30:
            print()
            print("Reached the goal!")
            break
    
    print(next(e), next(e), next(e))
    

    This produces:

    9 8 7 6 
    Reached the goal!
    9 8 7