Где хранится результат неприсвоенного выражения?
Если у нас есть вот такое выражение:
2 + 2
или любое другое, которое мы никуда не присваиваем, то PyCharm подскажет, что
Statement seems to have no effect
но интерпретатор ругаться не будет, код выполнится.
Вопрос - куда денется результат вычислений? Он вообще где-то будет хранится, а потом его мусорщик уберет или он вообще нигде не сохранится?
Ответы (1 шт):
Иногда оно хранится на вершине стека, иногда его нет вообще, иногда оно живёт вечно.
def f():
2 + 2
Дизассемблер dis даст такой код
4 0 RESUME 0 5 2 LOAD_CONST 0 (None) 4 RETURN_VALUE
Даже если вы не понимаете что происходит, вы видите, что среди инструкций нет сложения. Компилятор достаточно умён, чтобы понять что выражение 2 + 2
не имеет побочных эффектов, его результат нас не интересует, значит выражение может быть удалено. И он его удаляет.
Заставим компилятор вычислить сумму.
def g(a, b):
a + b
7 0 RESUME 0 8 2 LOAD_FAST 0 (a) 4 LOAD_FAST 1 (b) 6 BINARY_OP 0 (+) 10 POP_TOP 12 LOAD_CONST 0 (None) 14 RETURN_VALUE
В этом коде сложение есть: LOAD_FAST
, LOAD_FAST
, BINARY_OP
. Компилятор оставляет сложение, потому что он не знает типов a
и b
. Они могут оказаться определены пользователем так, что сложение будет иметь побочный эффект.
Интерпретатор Питона использует стек для хранения значений. Процедура сложения оставляет свой результат на вершине стека. Это, собственно, ответ на ваш вопрос.
Следующая инструкция – POP_TOP
. Она удаляет значение с вершины стека. Значение становится недоступно. Со временем все недоступные значения собирает сборщик мусора.
Тут нужна ремарка: все объекты в Питоне хранятся в свободной памяти, когда я говорю "значение лежит на вершине стека", это значит, что на вершине стека лежит указатель на объект в свободной памяти. Если удалили указатель из стека и это был последний указатель, указывающий на объект, тогда объект становится законной целью сборщика мусора.
Но результат 2 + 2
сборщик мусора не соберёт. Значение целых от -5 до 256 хранятся в кэше для ускорения работы и экономии памяти. Так что даже после инструкции POP_TOP
значение 4
, если получилось именно 4
, продолжает быть доступно из кэша и сборщик мусора его не убирает.