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


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

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

корпус 1:

def func():
    a = 42
    return a

корпус 2:

def func():
    return 42
2 103

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 массив текущего кадра выполнения. Затем, в обоих случаях это. Итак, второе всегда так немного быстрее из-за меньшего количества команд, необходимых для выполнения.

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

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

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

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

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

пока returning, это называется binding a возвращается в первом случае, когда объект 42 возвращается во втором случае.

для больше чтения, см. эта замечательная статья Неда Батчелдера