Язык программирования Python

Что эффективнее, if not == или if != в Pyhon?

В чем разница между следующими строками:

if not x == 'val':
Code language: JavaScript (javascript)

И

if x != 'val':
Code language: JavaScript (javascript)

Есть ли способ проверить, является ли одно из них более эффективным, чем другое?

Или, может быть, следующий блок будет лучше?

if x == 'val': pass else:
Code language: PHP (php)

Ответы.

Ответ 1.

Разбираемся.

Если мы воспользуемся дизассемблером для Python (dis), то увидим, что все три компилируются в одинаковое количество инструкций, и отличаются только POP_JUMP_IF_TRUE или POP_JUMP_IF_FALSE.

!= 0 LOAD_FAST 0 (x) 3 LOAD_CONST 1 ('val') 6 COMPARE_OP 3 (!=) 9 POP_JUMP_IF_FALSE 15
Code language: JavaScript (javascript)
not == 0 LOAD_FAST 0 (x) 3 LOAD_CONST 1 ('val') 6 COMPARE_OP 2 (==) 9 POP_JUMP_IF_TRUE 15
Code language: JavaScript (javascript)
== else 0 LOAD_FAST 0 (x) 3 LOAD_CONST 1 ('val') 6 COMPARE_OP 2 (==) 9 POP_JUMP_IF_FALSE 15
Code language: JavaScript (javascript)

Профиль

Используя cProfile, мы можем измерить время выполнения и провести сравнительный анализ:

ncalls tottime percall cumtime percall filename:lineno(function) not == 5000000 1.589 0.000 1.589 0.000 ./prog.py:8(en) == else 5000000 1.562 0.000 1.562 0.000 ./prog.py:12(ee) != 5000000 1.508 0.000 1.508 0.000 ./prog.py:4(ne)
Code language: JavaScript (javascript)

Отсортировав от самого медленного к самому быстрому, мы получим следующее:

  • if not x == ‘val’ является самым медленным.
  • if x == 'val' + else на ~1,7% быстрее.
  • if x != ‘val’ на ~3,6% быстрее.
  • Между самым медленным и самым быстрым мы экономим 81 мс.

Вывод

Условие if x != ‘val’ немного более эффективно.

Однако, на мой взгляд, разница не настолько существенна, чтобы менять стиль кодирования.

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

Ответ 2.

Все три делают одно и то же с точки зрения наблюдаемого поведения. Поэтому компилятор или интерпретатор python может сгенерировать/выполнить совершенно одинаковый код во всех трех случаях. В этом случае на выполнение потребуется точно такое же время, поскольку это один и тот же сгенерированный код. А наблюдаемые различия были бы шумом.

Может возникнуть соблазн разобрать сгенерированный код и увидеть, что он отличается во всех трех случаях. Но выводы, сделанные таким образом, будут применимы только к той версии python, с которой проводились тесты. Они не могут быть применимы в целом.

Давайте посмотрим, как использование двух разных методов выполнения этих инструкций дает разные результаты.

import time def not_same(): if not x == 'val': x def different(): if x != 'val': x def same_else(): if x == 'val': pass else: x def test(tam): start = time.time() i = 0 while (i<tam) : i = i + 1 end = time.time() empty = end-start start = time.time() i = 0 while (i<tam) : not_same() i = i + 1 end = time.time() print( 'Время not == ' + str(end-start-empty) ) start = time.time() i = 0 while (i<tam) : different() i = i + 1 end = time.time() print( 'Время != ' + str(end-start-empty) ) start = time.time() i = 0 while (i<tam) : same_else() i = i + 1 end = time.time() print( 'Время == else ' + str(end-start-empty) ) x='val' test(10000000)
Code language: PHP (php)

При запуске с помощью интерпретатора python были получены следующие результаты:

Время== 1.71001195908 Время!= 1.9246609211 Время== else 1.75712680817
Code language: JavaScript (javascript)

И если я запускаю его несколько раз, то получаю похожие результаты. Кажется, что победитель not ==.

Теперь я компилирую его в C с помощью cpython. А код на C я компилирую в двоичный файл ELF для linux, который я запускаю

diam@HP:~/t$ gcc -O2 -I /usr/include/python3.5m -o a a.c -lpython3.5m -lpthread -lm -lutil -ldl diam@HP:~/t$ ./a Время== 0.6007065773010254 Время!= 0.6298408508300781 Время== else 0.6232995986938477 diam@HP:~/t$ ./a Время== 0.5901763439178467 Время!= 0.6861095428466797 Время== else 0.6084094047546387 diam@HP:~/t$ ./a Время== 0.6090543270111084 Время!= 0.6182305812835693 Время== else 0.6077189445495605
Code language: JavaScript (javascript)

Теперь иногда побеждает один, а иногда другой.

Но я могу получить разные результаты не только в разных средах выполнения. При одинаковой среде выполнения результаты могут быть разными в зависимости от входных данных. Давайте изменим строку x=’val’ на x=’xxx’ и запустим снова с помощью команды :

diam@HP:~/t$ gedit a.py diam@HP:~/t$ python a.py Время not == 2.22967505455 Время != 2.49930405617 Время == else 2.18658304214

Теперь побеждает == else.

Когда я запускаю его несколько раз, этот результат повторяется. А я запускаю его с точно такой же системой, где раньше победитель был not ==, изменились только входные данные.

Ни один из предыдущих бенчмарков не подходит.

Во всех тестах значение x всегда одинаково от начала до конца теста.

Следует проводить тестирование на случайных данных или, что еще лучше, на данных, полученных из ситуации, аналогичной той, в которой, как ожидается, будет работать наша программа.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *