Предположим, у меня есть if
утверждение с return
. С точки зрения эффективности, следует ли мне использовать
if(A > B):
return A+1
return A-1
или
if(A > B):
return A+1
else:
return A-1
Что лучше выбрать при использовании компилируемого языка (C) или скриптового (Python)?
python
c
performance
compiler-construction
Хорхе Лейтао
источник
источник
Ответы:
Поскольку
return
оператор завершает выполнение текущей функции, эти две формы эквивалентны (хотя вторая, возможно, более читабельна, чем первая).Эффективность обеих форм сопоставима, базовый машинный код должен выполнить переход, если
if
условие все равно ложно.Обратите внимание, что Python поддерживает синтаксис, который позволяет вам использовать только один
return
оператор в вашем случае:return A+1 if A > B else A-1
источник
return (A>B)?A+1:A-1;
Однако от написания такого кода нет абсолютно никакого выигрыша в производительности . Все, что мы достигли, - это сделать код запутанным, нечитаемым и в некоторых случаях более уязвимым для неявного продвижения типов.<
это плохая практика, потому что-1 < 1u
дает неожиданный результат.-1 < 1u
, в чем я сомневаюсь, он легко обнаружил бы ошибку. Однако довольно много людей напишут ту или иную версию кода, который я опубликовал. Я слишком часто встречал такие ошибки в производственном коде, чтобы доверять оператору? :. Также, как показывает опыт, если язык дает вам два разных способа сделать одно и то же, используйте только один из них, не выбирайте случайно ни один из двух в зависимости от вашего настроения.Из руководства по стилю Chromium :
Не используйте другое после возврата:
# Bad if (foo) return 1 else return 2 # Good if (foo) return 1 return 2 return 1 if foo else 2
источник
if-else-return
ветки почти никогда не равны (если они равны, вам все равно следует провести рефакторинг; либо с помощьюswitch
конструкции, либо для Python, перечисляя dict / используя вызываемый / и т. д.). Таким образом, почти всеif-else-return
являются случаями защитных предложений, и они всегда проверяются (имитируют проверяемое выражение) без использованияelse
.Что касается стиля кодирования:
Большинство стандартов кодирования, независимо от языка, запрещают множественные операторы возврата из одной функции как плохую практику.
(Хотя лично я бы сказал, что есть несколько случаев, когда несколько операторов return имеют смысл: парсеры протокола текста / данных, функции с обширной обработкой ошибок и т. Д.)
Все эти отраслевые стандарты кодирования пришли к единому мнению, что выражение должно быть записано как:
int result; if(A > B) { result = A+1; } else { result = A-1; } return result;
По поводу эффективности:
Приведенный выше пример и два примера в вопросе полностью эквивалентны с точки зрения эффективности. Во всех этих случаях машинный код должен сравнивать A> B, затем переходить к вычислению A + 1 или A-1, а затем сохранять результат в регистре ЦП или в стеке.
РЕДАКТИРОВАТЬ :
Источники:
источник
return
там, где это кажется ясным, является идиоматическим способом сделать это в Python.С любым разумным компилятором вы не должны замечать никакой разницы; они должны быть скомпилированы в идентичный машинный код, поскольку они эквивалентны.
источник
Я лично избегаю
else
блоков, когда это возможно. См. Кампанию Anti-IfКроме того, они не взимают дополнительную плату за линию, вы знаете: p
«Простое лучше, чем сложное» и «Читаемость - главное»
delta = 1 if (A > B) else -1 return A + delta
источник
dict
s для предотвращения различий - очень плохая идея с точки зрения производительности.Это вопрос стиля (или предпочтений), так как переводчику все равно. Лично я бы попытался не делать окончательный оператор функции, которая возвращает значение на уровне отступа, отличном от базы функции. Else в примере 1 скрывает, хотя и немного, где находится конец функции.
По желанию я использую:
return A+1 if (A > B) else A-1
Поскольку он подчиняется как хорошему соглашению о наличии единственного оператора возврата в качестве последнего оператора в функции (как уже упоминалось), так и хорошей парадигме функционального программирования, позволяющей избежать промежуточных результатов императивного стиля.
Для более сложных функций я предпочитаю разбивать функцию на несколько подфункций, чтобы избежать преждевременного возврата, если это возможно. В противном случае я возвращаюсь к использованию переменной императивного стиля под названием rval. Я стараюсь не использовать несколько операторов возврата, если функция не является тривиальной или оператор возврата до конца не является результатом ошибки. Преждевременное возвращение подчеркивает тот факт, что вы не можете продолжать. Для сложных функций, которые предназначены для разделения на несколько подфункций, я стараюсь кодировать их как операторы case (например, управляемые dict).
В некоторых плакатах упоминалась скорость работы. Скорость выполнения для меня второстепенна, поскольку, если вам нужна скорость выполнения, Python - не лучший язык для использования. Я использую Python, поскольку он важен для меня как эффективность кодирования (т.е. написание кода без ошибок).
источник
var n = 1 if (A > B) else -1
return A+n
Версия А проще, поэтому я бы ее и использовал.
И если вы включите все предупреждения компилятора в Java, вы получите предупреждение о второй версии, потому что это не имеет значения и увеличивает сложность кода.
источник
Я знаю, что вопрос помечен как python, но в нем упоминаются динамические языки, поэтому я подумал, что должен упомянуть, что в ruby оператор if на самом деле имеет тип возврата, поэтому вы можете сделать что-то вроде
def foo rv = if (A > B) A+1 else A-1 end return rv end
Или потому, что он также имеет неявный возврат просто
def foo if (A>B) A+1 else A-1 end end
который довольно хорошо решает проблему стиля отсутствия множественных возвратов.
источник