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

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

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

Случай 1:

def func():
    a = 42
    return a

Случай 2:

def func():
    return 42

2 ответа

Решение

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

Компиляция в байт-код CPython проходит только через небольшой глазковый оптимизатор, который предназначен для выполнения только базовых оптимизаций (см. 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 массив текущего кадра выполнения. Тогда в обоих случаях RETURN_VALUE выполняется. Таким образом, вторая намного быстрее из-за меньшего количества команд, необходимых для выполнения.

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

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

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

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

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

В то время как returnИнг, это именованное связывание a возвращается в первом случае, пока объект 42 это возврат во втором случае.

Для получения дополнительной информации обратитесь к этой замечательной статье Неда Батчелдера.

Другие вопросы по тегам