Search code examples
pythongenerator

What is the difference between exhausting a generator using "for i in generator" and next(generator)


I want to learn how to use the return value of a generator (but this not what I'm concerned with now).

After searching, they said that I can get the return value from StopIteration when the generator is exhausted, so I tested it with the following code:

def my_generator():
    yield 1
    yield 2
    yield 3
    return "done"


def exhaust_generator(_gen):
    print("===============================================\n")
    print("exhaust_generator")
    try:
        while True:
            print(next(_gen))
    except StopIteration as e:
        print(f"Return value: '{e.value}'")


def exhaust_generator_iter(_gen):
    print("===============================================\n")
    print("exhaust_generator_iter")
    try:
        for i in _gen:
            print(i)
        print(next(_gen))
    except StopIteration as e:
        print(f"Return value: {e.value}")


gen = my_generator()
gen2 = my_generator()
exhaust_generator(gen)
exhaust_generator_iter(gen2)

===============================================

exhaust_generator
1
2
3
Return value: 'done'
===============================================

exhaust_generator_iter
1
2
3
Return value: None

As you can see, the return value is different between the two versions of exhausting the generator and I wonder why.

Searched google but it has not been helpful.


Solution

  • In your first example with the while, you're catching the first StopIteration exception raised by the generator when it's initially exhausted.

    In your second example with the for, you're catching a subsequent StopIteration exception raised by calling next() a second time after the generator has already been exhausted (by the for, which caught that initial exception).