В чем разница между следующими строками:
if not x == 'val':
Д
if x != 'val':
Есть ли способ проверить, является ли один более эффективным, чем другой?
Или, возможно, следующий блок был бы лучше:
if x == 'val':
pass
else:
В чем разница между следующими строками:
if not x == 'val':
Д
if x != 'val':
Есть ли способ проверить, является ли один более эффективным, чем другой?
Или, возможно, следующий блок был бы лучше:
if x == 'val':
pass
else:
разобранный
Если мы воспользуемся дизассемблером для Python (
dis
) , то увидим, что все 3 компилируются с одинаковым количеством инструкций и отличаются толькоPOP_JUMP_IF_TRUE
oPOP_JUMP_IF_FALSE
Demo en ideone
профиль
Используя cProfile , мы можем измерить время выполнения и выполнить тест :
Отсортировав от самого медленного к самому быстрому, мы видим, что:
if not x == 'val'
это самый медленный.if x == 'val'
+else
на ~ 1,7% быстрее.if x != 'val'
это ~ 3,6% даже быстрее.Demo en ideone
* Или вот более сложный пример для сравнения истинных и ложных случаев со случайными строками.
вывод
Состояние
if x != 'val'
немного более эффективное.Однако, на мой взгляд, разница не настолько значительна, чтобы менять стиль при кодировании. Я абсолютно предпочитаю, чтобы код был как можно более легко читаемым, и я бы подумал об учете этого результата только в чрезвычайно интенсивных вычислениях, требующих экономии каждой возможной доли секунды.
Все три берут одинаково
Сравнительный анализ — это непросто
Все три делают то же самое с точки зрения наблюдаемого поведения. Таким образом, компилятор или интерпретатор Python может генерировать/выполнять один и тот же код во всех трех случаях. В этом случае для выполнения потребуется точно такое же время, потому что это один и тот же сгенерированный код. И наблюдаемые различия будут шумом.
Может возникнуть соблазн разобрать сгенерированный код и увидеть, что он отличается во всех трех случаях. Но выводы, полученные таким образом, будут применимы только к той версии Python, с которой проводились тесты. Они не будут применимы в целом.
Давайте посмотрим, как, используя два разных метода выполнения этих инструкций, мы получаем разные результаты. Рассмотрим следующую программу:
При выполнении его с помощью интерпретатора python получены следующие результаты:
И если я запускаю его несколько раз, я получаю одинаковые результаты. Похоже, победитель не == .
Теперь я компилирую его в C с помощью cpython. И код C, который я компилирую в двоичный файл ELF для Linux, который я выполняю:
Теперь иногда выигрывает один, а иногда выигрывает другой.
Но я не только могу получить разные результаты с разными средами выполнения. В одной и той же среде выполнения результаты могут различаться в зависимости от входных данных. Давайте изменим строку
x='val'
наx='xxx'
и снова запустим интерпретатор:Теперь побеждает == else . И при выполнении его несколько раз этот результат повторяется. И я запускаю его с точно такой же системой, где раньше победителя не было == , только ввод изменился.
И ни один из вышеперечисленных тестов не является хорошим. Во всех тестах значение
x
всегда одинаково от начала до конца теста. Также было бы необходимо провести тестирование со случайными данными или, еще лучше, с данными, полученными из ситуации, похожей на ту, в которой ожидается запуск нашей программы. Мы можем обнаружить такие сюрпризы, как упорядоченные данные, которые обрабатываются быстрее, чем случайные данные ; таким образом удаляя всю ценность до чрезмерно простого эталона, как представлено выше.Я думаю, что нет необходимости сравнивать эти операторы сравнения, чтобы определить, намного ли один из них эффективнее другого, в основном потому, что вычисления выполняются настолько быстро, что почти невозможно обнаружить разницу.
Однако, на мой взгляд, есть различия при сравнении с тем или другим.
Теоретически использовать
более эффективно, чем использование
Основная причина в том, что != выполняет сравнение напрямую и спрашивает, отличается ли x от z . Вместо этого not x == z выполняет две операции вместо одной, поскольку сначала проверяет, равен ли x значению z , а затем отрицает результат этой операции.
С другой стороны, мы должны принимать во внимание контекст, в котором мы проводим сравнение, ведь от этого зависит использование того или другого. Под этим я подразумеваю, что бывают случаи, когда гораздо понятнее читать и интерпретировать фрагмент кода с использованием not , чем с использованием != , пример:
Я нахожу следующую строку кода более читаемой:
что это:
И поскольку я говорю о читабельности кода, я бы посоветовал не использовать зарезервированные слова, такие как pass или break , потому что они резко прерывают поток кода и затрудняют его чтение, делая его сложным и непонятным. Настолько, что некоторые считают это спагетти-кодом .
Различия во времени я получил крайне минимальные, используя следующий алгоритм:
Среднее значение составляло от 12 до 14 тысячных секунды, при этом
if
TRUE
; и от 9 до 13 миллисекунд, сif
FALSE
.Позиции от самого быстрого к самому медленному распределились следующим образом:
if
TRUE
if x == 'val'
if x != 'val'
if not x == 'val'
if
FALSE
if x != 'val'
if not x == 'val'
if x == 'val'
Согласно модели данных Python , если класс не реализует метод
__ne__
, он делегирует этому методу__eq__
. Поэтому считается, что проверка более эффективна,a == b
чем проверкаa != b
.С другой стороны, проверка
if not
считается одной атомарной операцией по замыслу, а не из-за причуд реализации интерпретатора (как было предложено в каком-то комментарии), точно так же, как было решено, что операцииnot a is b
и эквивалентныa is not b
.Таким образом, правильный ответ должен быть более эффективным
if not x == y
. Но это не так с нативными типами python , так как в них обычно реализованы все методы модели данных, кроме того, что их вызов гораздо более оптимизирован по сравнению с созданными пользователями методами.Мой совет — не зацикливаться на производительности, поскольку улучшения происходят из других источников, например, сравниваемые переменные являются локальными (вместо глобальных) или генерирование выражений в сочетании с функциями
any()
илиall()
вместо типичных циклов с некоторыми файламиif
.На мой взгляд обе функции одинаковые, бывает что в первой:
Вы обусловливаете утверждение условия отрицанием, то есть, если НЕ верно, что X равно val, тогда сделайте что-нибудь, запустите if, иначе, если это правда, что X есть VAL, тогда сделайте что-то еще
во-вторых
Вы делаете то же самое, но говорите:
Если X отличается от VAL, сделайте что-нибудь еще, если X не равно VAL, сделайте что-нибудь еще
Кажется, я работаю с методом != отличным от . так как вы не ставите условие с самого начала отрицать весь оператор, который находится в IF
Кроме того, читая о том, как python работает с этими двумя компараторами, первый преобразует его в логическое значение, почему?Почему он будет спрашивать объект «Выполняется логическое условие или нет?»
а второй спросит "Вы равны этому значению?"
Что касается вашего примера:
вы заявляете, что если X равно Value, сделайте что-нибудь, используемый метод будет основан на ваших потребностях.
чтобы узнать, равно ли значение переменной для входа в систему, X == val
Я собираюсь дать вам ответ, не основанный на разборке или анализе времени...
Как программист на Python, для вас это почти то же самое в 99,99% случаев. Очень редко что-то подобное влияет на скорость вашего скрипта. На самом деле, тратить время на эти «микрооптимизации» даже вредно, так как наверняка есть и другие возможные улучшения на алгоритмическом уровне.
Даже при более сложных операциях, таких как конкатенация строк, выигрыш обычно незначителен.