I've been digging around the source code to figure-out at which point the result is printed. For example:
>>> x = 1
>>> x + 2
3
The above two statements are compiled to:
1 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (x)
6 LOAD_CONST 1 (None)
9 RETURN_VALUE
and
1 0 LOAD_NAME 0 (x)
3 LOAD_CONST 0 (2)
6 BINARY_ADD
7 RETURN_VALUE
The first statement doesn't print anything because None
is the returned value. The second returns the result of the addition.
CPython's interactive loop calls PyRun_InteractiveOneObjectEx()
for each input. This gets the AST and invokes run_mod()
to compile that AST to byte code and then evaluate the result in the virtual machine. The returned Python object that PyRun_InteractiveOneObjectEx()
gets is simply the top of the VM's stack.
So far all of this is what I would expect. But then the returned value seems to be thrown away! When is this printed by the REPL?
As an aside, I can see that interactive mode does change the tokenizer; it invokes PyOS_Readline
with the sys.ps1
prompt (">>> "
by default). I checked for a similar change in pythonrun.c
, but no luck.
You are showing disassemblies of the bytecode as generated by having the code in a function. That isn't how interactive code is compiled: it uses a special 'single' mode (3rd parameter to compile()
, if you were doing the equivalent in Python code). In this mode, the POP_TOP
opcode that discards the value of each expression gets turned into a PRINT_EXPR
instead. The reason why x = 1
prints nothing is that statements leave nothing on the stack that needs to be popped, so this transformation doesn't apply.