Пайтон: Что более работоспособный if not == или if! =?

Каково различие между следующими линиями:

if not x == 'val':

и

if x != 'val':

Существует какой-то способ подтверждать, работоспособнее ли, чем другая одна?

или: возможно следующий блок был бы лучше?:

if x == 'val':
    pass
else:
19
задан 11.09.2016, 12:09
6 ответов

Desensamblado

Если мы используем desensamblador для Пайтона (dis), мы видим, что 3 составляют в то же количество инструкций, и только различаются в 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

not ==
              0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 ('val')
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_TRUE        15

== else
              0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 ('val')
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_FALSE       15

Demo в ideone



Profile

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

          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)

Упорядоченные более медленного в более быстрый, мы можем видеть, что:

  • if not x == 'val' он самый медленный.
  • if x == 'val' + else это ~1.7 % более быстрых.
  • if x != 'val' это ~3.6 % еще более быстрых.
  • Между самым медленным и самым быстрым только мы избавляем 81ms / от 5 миллионов сравнений.

Demo в ideone

* Или здесь я оставляю более сложный пример, чтобы сравнивать истинные и фальшивые случаи с strings случайные.



Заключение

Условие if x != 'val' он незначительно работоспособнее.

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

23
ответ дан 24.11.2019, 13:25
  • 1
    Поздравления из-за ответа, но что различие есть в чтении if not x == val с if x! = и #39; val и # 39; я это говорю, потому что он мне кажется, что instrucci и # 243; n м и # 225; s r и # 225; попросите, чтобы это была несомненно та, которая понимает себя лучше, из-за того, что очень com и # 250; n между языками programaci и # 243; n. – Webserveis 11.09.2016, 09:17
  • 2
    Tambi и # 233; n я думаю, что в общий способ это м и # 225; s простой читать !=, но я представляю себе то, что habr и # 225; ситуации в одном c и # 243; я говорю м и # 225; s комплекс, где, например, был распределен condicion = (x == 'val'), и м и # 225; s вперед использовали if not condicion. Конечно, все зависит от стиля, свойственного каждому программисту. Точка, которую я захотел пометить, состоит в том, что с не такими значительными различиями, годится оказывать предпочтение opci и # 243; n, что внес м и # 225; s читабельность в c и # 243; я говорю. – Mariano 11.09.2016, 09:23
  • 3
    #191; Podr и # 237; хозяева видеть c и # 243; я говорю твоего benchmark? – Jose Antonio Reinstate Monica 11.09.2016, 12:01
  • 4
    @JoseAntonioDuraOlmos est и # 225; в ответе, кликая в " Demo в ideone ". Это использование t и # 237; пик cProfile, из-за которого не consider и # 233; значимый включать c и # 243; я говорю прямо (уменьши м и # 225; s, которого он достигает). – Mariano 11.09.2016, 12:04
  • 5
    C и # 225; mbia она l и # 237; nea x = 'valor diferente' из-за x = 'val' и obtendr и # 225; s различные результаты. Следовательно не возможно заключать этого benchmark, который! = были ~3.6 % м и # 225; s r и # 225; я прошу. Три опаздывают то же самое. Любое наблюдаемое различие - шум или деталь implementaci и # 243; n compilador/int и # 233; rprete, что не extrapolable в общий случай. – Jose Antonio Reinstate Monica 11.09.2016, 12:16

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

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

Теоретически, использовать

x != z

он работоспособнее, который использовать

not x == val

Главный разум - потому что! = реализуй прямо сравнение и спроси, если x он отличается z. Взамен, not x == z реализуй две операции вместо одной, потому что сначала он санкционирует, если x он равен в z и потом отрицает результат этой операции.

С другой стороны, нужно иметь в виду контекст, в котором мы делаем сравнение, в самом деле, этим, зависит использование одного или другой. То, что я хочу сказать с этим, состоит в том, что есть разы, которыми оказывается гораздо более ясным читать и интерпретировать часть кода с использованием not, что с использованием! =, пример:

valid = 1 > 2; // false

Мне кажется более читабельной следующая линия кода:

if not valid:
  ...

что:

if valid != true:
  ...

И так как я говорю о читабельности кода, он советовал бы не использовать слова, размещенные как pass или break благодаря тому, что эти прерывают разгрузку кода немного крутого способа, и он затрудняет читабельность того же самого, способствуя тому, чтобы этот стал сложным и непонятным. Так так, что какие-то считают это Кодом espaguetti.

4
ответ дан 24.11.2019, 13:25
  • 1
    " not x == z реализует две операции " < - это не верно. C и # 243; я говорю, что составленный он заканчивается тем же количеством инструкций... Я соглашаюсь полностью с оставшейся частью. – Mariano 11.09.2016, 08:34
  • 2
    Договора, большое спасибо из-за aclaraci и # 243; n, я это сказал в форме hipot и # 233; костариканская, потому что никогда я не делал тесты, чтобы это показывать. – Mauro Aguilar 11.09.2016, 08:43
  • 3
    " not x == z реализуй два operaciones" <---S и # 237; это верно. Есть или может быть compiladores/int и # 233; rpretes python, в котором произвелись две операции, и я закончился одним c и # 243; я говорю произведенный менее работоспособный, чем " x! =z". Нет, это не верно. Есть или могут быть составители python, в которых он был бы оптимизирован c и # 243; я говорю произведенный и окажитесь экс-и # 225; ctamente в том же самом, что " x! =z". С тем, что верное или фальшивое в зависимости от int и # 233; rprete/compilador использованный. Не возможно утверждать, что это не верно в общем, ни, что s и # 237; это было верно в общем. – Jose Antonio Reinstate Monica 11.09.2016, 12:08

Опаздывают то же самое три

Делать benchmarking не легко

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

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

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

import time

def not_igual():
  if not x == 'val':
    x

def distinto():
  if x != 'val':
    x

def igual_else():
  if x == 'val':
    pass
  else:
    x

def test(tam):

 inicio = time.time()
 i = 0
 while (i<tam) :
   i = i + 1
 fin = time.time()
 vacio = fin-inicio

 inicio = time.time()
 i = 0
 while (i<tam) :
   not_igual()
   i = i + 1
 fin = time.time()
 print( 'Tiempo not ==  es ' + str(fin-inicio-vacio)  )

 inicio = time.time()
 i = 0
 while (i<tam) :
   distinto()
   i = i + 1
 fin = time.time()
 print( 'Tiempo !=      es ' + str(fin-inicio-vacio)  )

 inicio = time.time()
 i = 0
 while (i<tam) :
   igual_else()
   i = i + 1
 fin = time.time()
 print( 'Tiempo == else es ' + str(fin-inicio-vacio)  )

x='val'
test(10000000) 

Выполнив это с переводчиком этих python это полученные результаты:

jose2@HP-Negro:~/t$ python a.py
Tiempo not ==  es 1.71001195908
Tiempo !=      es 1.9246609211
Tiempo == else es 1.75712680817

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

Сейчас я это составляю в C с cpython. И код C составил в бинарный ELF для linux, который я выполняю:

jose2@HP-Negro:~/t$ gcc -O2 -I /usr/include/python3.5m -o a a.c -lpython3.5m -lpthread -lm -lutil -ldl
jose2@HP-Negro:~/t$ ./a
Tiempo not ==  es 0.6007065773010254
Tiempo !=      es 0.6298408508300781
Tiempo == else es 0.6232995986938477
jose2@HP-Negro:~/t$ ./a
Tiempo not ==  es 0.5901763439178467
Tiempo !=      es 0.6861095428466797
Tiempo == else es 0.6084094047546387
jose2@HP-Negro:~/t$ ./a
Tiempo not ==  es 0.6090543270111084
Tiempo !=      es 0.6182305812835693
Tiempo == else es 0.6077189445495605

Сейчас разы заработай один и другие разы заработай другой.

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

jose2@HP-Negro:~/t$ gedit a.py
jose2@HP-Negro:~/t$ python a.py
Tiempo not ==  es 2.22967505455
Tiempo !=      es 2.49930405617
Tiempo == else es 2.18658304214

Сейчас это == else тот, который преуспевает. И несколько раз этот результат повторяется ejectarlo. И я это выполняю с exáctamente ту же систему, в которой раньше победитель был not ==, только они изменили данные о вводе.

И ни один из предыдущих benchmarks не является хорошим. Во всех доказательствах стоимость x это всегда тот же самый от начала до конца доказательства. Было бы нужно пытаться также со случайными данными или, наиболее еще, с данными, полученными от ситуации, сходной в ту, которая ожидается, что работала наша программа. Мы можем встречаться с сюрпризами, как которые аккуратные данные были бы обработаны быстрее, чем случайные; лишая так каждой стоимости чрезмерно простой benchmark как представленное ранее.

6
ответ дан 24.11.2019, 13:25

Различия во времени, которых я достиг, были крайне минимальными, используя следующий алгоритм:

import time, array
#Las pruebas las realicé con cada una de las dos siguientes líneas:
#x,y = 'val','lav'
#x,y = 'va1','lav'

print (x,y)
t = array.array('d')
suma = 0

for j in range(0,100):
    ti = time.process_time()

    for i in range (0,100000):
        if x == 'val':    # not x == 'val'    # x != 'val'
            y = 'val'

    tf = time.process_time()

    dif = tf - ti
    t.append(dif)

    suma += dif

print ('Promedio = ', suma / 100)

Средняя величина была между пятнадцатитысячными секунды, с if TRUE; и между 9 и 13 миллисекундами, с if FALSE.

Положения более быстрой в более медленную, это были следующие:

if TRUE

  1. if x == 'val'
  2. if x != 'val'
  3. if not x == 'val'

if FALSE

  1. if x != 'val'
  2. if not x == 'val'
  3. if x == 'val'
3
ответ дан 24.11.2019, 13:25
  • 1
    Сравнив в различном выполнении, времена var и # 237; an незначительно seg и # 250; n условия системы в этом моменте. Чтобы сравнивать времена ejecuci и # 243; n, годится реализовывать это всегда внутри той же программы, и даже вставляя доказательство с другой. Таким образом, x != 'val' - м и # 225; s работоспособный включенный, когда x = 'val'. – Mariano 11.09.2016, 08:10
  • 2
    Спасибо за aclaraci и # 243; n и из-за тебя c и # 243; я говорю, возможно изучать много estudi и # 225; ndolo, и м и # 225; s для м и # 237; который я наставляю в Пайтон . Схвати и # 237; он, как говоришь ты, поэтому implement и # 233; array t, чтобы уменьшать в м и # 225; ximo любое вмешательство в medici и # 243; n, но улучшаемый, если мы продолжаем твой совет. Мой conclusi и # 243; n вслед за несколькими доказательствами, дело в том, что не существует установленное место ни для одного из вариантов, хотя верно, что !=, обычно обгоняет в оставшуюся часть. Даже, если доказательства несколько раз ты c и # 243; я говорю видеть и # 225; s, что обмениваются положениями, например: ne-en-ee, en-ne-ee, ne-ee-en – Aprendiendo.NET 11.09.2016, 09:06
  • 3
    Способ это исправлять podr и # 237; чтобы быть используя 3 arrays, и звоня в 3 м и # 233; все, добавляя время к каждому соответствующему array, чтобы потом доставать среднюю величину на каждом. Относительно доказательств, 2 м и # 225; s медленные они могут interambiar порядок иногда благодаря тому, что не est и # 225; n тестируя достаточно времени, чтобы помечать различие, и est и # 225; n тестируя почти время, потому что она p и # 225; gina где publiqu и # 233; у него есть один м и # 225; ximo ejecuci и # 243; n 5 seg. Если он тестируется м и # 225; s время, это поведение стабилизируется. – Mariano 11.09.2016, 09:32

Согласно Модели Данных Пайтона, если класс не осуществляет метод __ne__, он уполномочивается в методе __eq__. Следовательно предполагает работоспособнее подтверждать a == b который подтверждать a != b.

С другой стороны, проверка if not она считается единственной атомной операцией, из-за рисунка, не из-за капризов осуществления переводчика (как он предлагается в каком-то комментарии), так же быть решенным, что были эквивалентными операции not a is b и a is not b.

Итак, правильный ответ должен бы быть работоспособнее if not x == y. Но ésto не является верным с родными типами python, так как они обычно считают осуществленными все методы модели данных, кроме того, что Ваш призыв гораздо более оптимизирован по сравнению с методами, созданными пользователем.

Мой совет состоит в том, чтобы не быть одержимым результатом, так как прогресс приходит из другой части, как которая переменные, которые нужно сравнивать, - локальные (вместо того, чтобы использовать глобальные), или что сочетали порождающие выражения с функциями any() или all() вместо типичных циклов с какой-то if.

3
ответ дан 24.11.2019, 13:25

Для меня казаться обоими это та же функция, происходи, чем в первой:

if not x == 'val':

Ты обусловливаешь в отрицание решение об условии, а именно, если не выполняется, что X был равен в val, тогда сделайте что-то, скроллируй if, иначе, если, ЕСЛИ выполняется, что X было VAL, тогда он сделал другую вещь

во второй

if x != 'val':

Ты делаешь то же самое, но говоришь:

Если X отличается от VAL, тогда сделайте что-то, иначе, если X не равен VAL, тогда сделайте другую вещь

мне кажется работать с методом! = различный. так как ты не обусловливаешь с начала, которое должно отрицать все решение, которое находится в IF

Добавочный, читая о, как работает python этот два comparadores, первый это обращает в booleano, потому что?, потому что он задаст вопрос с целью "логическое условие выполняется или нет?"

и вторая спросит у него "Ты равен этой стоимости?"

Относительно твоего примера:

if x == 'val':
pass
else:

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

чтобы знать, равна ли стоимость переменной для того, чтобы он вошел в систему, X == val

2
ответ дан 24.11.2019, 13:25