Search code examples
pythonpython-2.7generatoryieldpython-internals

Disassembling a generator yields surprising results


I know how to use generators but I don't know anything about their internals. I tried this:

In [4]: def f(): yield 1
In [6]: type(f())
Out[6]: generator

Now I disassemble it:

In [7]: dis.dis(f)
  1           0 LOAD_CONST               1 (1)
              3 YIELD_VALUE         
              4 POP_TOP             
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE        

Why does the opcodes suggest return None while f actually returns a generator?


Solution

  • All functions return None at their end if there is no explicit return, generators are no exception. As of Python 3.3, generators can return a final value when ending, but in Python 2.7 a blank return is mandatory if you use return to end the function early.

    This is a 'limitation' of how Python frames are implemented; you have to have a RETURN_VALUE opcode to exit the frame cleanly and unwind the stack, and that opcode requires an operand, always.

    Calling the function still produces a generator, but the byte code isn't executed until you actually call the .next() method on the generator.