def fib_gen(): x, y = 1, 1 while x < 100: x, y = y, x + y yield x return
I also remember the first time I tried to mix a return value into my generator.
def fib_gen(): x, y = 1, 1 while x < 100: x, y = y, x + y yield x return True
Imagine my surprise, as I'm sure countless others experienced as well:
SyntaxError: 'return' with argument inside generatorA rare compile-time error! Only the decorative, bare return is allowed in generators, where they serve to raise StopIteration.
Now, imagine my surprise, so many years later when I import that same code in Python 3.
...
Nothing! No error. So what happened?
Turns out that the coroutine and asyncio machinery of Python 3 has repurposed this old impossibility.
If we manually iterate to skip over our yield:
fib_iter = fib_gen() for i in range(11): next(fib_iter) next(fib_iter)
We see what's really happening with our return:
Traceback (most recent call last): File "fib_gen.py", line 13, in <module> next(fib_iter) StopIteration: True
That's right, returns in generators now raise StopIteration with a single argument of the return value.
Most of the time you won't see this. StopIterations are automatically consumed and handled correctly by for loops, list comprehensions, and sequence constructors (like list). But it's yet another reason to be extra careful when writing your own generators, specific to Python 3.