Удаляет ли Python переменную, которая используется только как возвращаемое значение?

Есть ли какая-либо принципиальная разница между следующими двумя фрагментами кода? Первый присваивает значение переменной в функции и затем возвращает эту переменную. Вторая функция просто возвращает значение напрямую.

Включает ли Python их эквивалентный байт-код? Один из них быстрее?

Случай 1:

def func():
    a = 42
    return a

Случай 2:

def func():
    return 42

Ответ 1

Нет, это не так.

Компиляция для байтового кода CPython передается только через небольшой оптимизатор peephole, который предназначен только для базовых оптимизаций (см. test_peepholer.py в наборе тестов для получения дополнительной информации об этих оптимизациях).

Чтобы посмотреть, что на самом деле произойдет, используйте dis *, чтобы увидеть созданные команды. Для первой функции, содержащей присвоение:

from dis import dis
dis(func)
  2           0 LOAD_CONST               1 (42)
              2 STORE_FAST               0 (a)

  3           4 LOAD_FAST                0 (a)
              6 RETURN_VALUE

Пока для второй функции:

dis(func2)
  2           0 LOAD_CONST               1 (42)
              2 RETURN_VALUE

В первом используются две более быстрые команды: STORE_FAST и LOAD_FAST. Они быстро хранят и захватывают значение в массиве fastlocals текущего кадра выполнения. Затем в обоих случаях выполняется a RETURN_VALUE. Итак, второй из них настолько немного быстрее из-за меньшего количества команд, необходимых для выполнения.

В общем, имейте в виду, что компилятор CPython является консервативным в своих оптимизациях. Он не является и не пытается быть таким же умным, как другие компиляторы (что, в общем, также имеет гораздо больше информации для работы). Основная цель проекта, помимо очевидного правильности, заключается в том, чтобы: a) сохранить ее просто и b) быть максимально быстрой при компиляции, чтобы вы даже не заметили, что существует фаза компиляции.

В конце концов, вы не должны беспокоиться о небольших проблемах, подобных этому. Преимущество в скорости крошечное, постоянное и затмевается из-за накладных расходов, вызванных тем фактом, что Python интерпретируется.

* dis - это небольшой модуль Python, который не собирает ваш код, вы можете использовать его для просмотра Python байт-код, который будет выполнять VM.

Примечание.. Как также указано в комментарии @Jorn Vernee, это специфично для реализации Python на CPython. Другие реализации могут делать более агрессивные оптимизации, если они этого желают, CPython не делает.

Ответ 2

Оба они в основном одинаковы, за исключением того, что в первом случае объект 42 просто присваивается переменной с именем a или, другими словами, имена (т.е. a) относятся к значениям (т.е. 42). Он не выполняет каких-либо присвоений технически, в том смысле, что он никогда не копирует никаких данных.

Пока return ing, это имя привязки a возвращается в первом случае, а объект 42 возвращается во втором случае.

Подробнее читайте эта замечательная статья Нед Батчелдера