Оптимизирует ли 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
это возврат во втором случае.
Для получения дополнительной информации обратитесь к этой замечательной статье Неда Батчелдера.