Правильный ответ от @ jasonharper !Для потомков, здесь более глубокий взгляд на то, что происходит.
Вышеприведенная разборка показывает результаты режима eval
:
>>> list(compile('x + 2', '<stdin>', 'eval').co_code)
[101, 0, 0, 100, 0, 0, 23, 83]
Код операции можно просмотреть с помощью:
>>> import dis
>>> dis.opname[101]
'LOAD_NAME'
>>> dis.opname[100]
'LOAD_CONST'
>>> dis.opname[23]
'BINARY_ADD'
>>> dis.opname[83]
'RETURN_VALUE'
Два числа, следующие за кодом операции, представляют 16-битный операнд, хотя нам нужен только первый байт.Так что это соответствует:
LOAD_NAME 0
LOAD_CONST 0
BINARY_ADD
RETURN_VALUE
Эти операнды являются индексами соответственно имен переменных и пула констант объекта скомпилированного кода.
>>> c = compile('x + 2', '<stdin>', 'eval')
>>> c.co_names
('x',)
>>> c.co_consts
(2,)
Пока это то, что мы имеем ввопрос.Но в действительности выполнение кода Python приводит к:
>>> list(compile('x + 2', '<stdin>', 'exec').co_code)
[101, 0, 0, 100, 0, 0, 23, 1, 100, 1, 0, 83]
>>> dis.opname[1]
'POP_TOP'
Т.е. результат отбрасывается, и в качестве возвращаемого значения вводится None
.
В интерактивном режиме мы имеем:
>>> list(compile('x + 2', '<stdin>', 'single').co_code)
[101, 0, 0, 100, 0, 0, 23, 70, 100, 1, 0, 83]
>>> dis.opname[70]
'PRINT_EXPR'
Результат печатается (через sys.displayhook
) и None
становится фактическим возвращаемым значением.
Таким образом, печать вводится кодомфаза генерации, а не виртуальной машиной