Python if not = = vs if!=

Jaka jest różnica między tymi dwoma liniami kodu:

if not x == 'val':

I

if x != 'val':
Czy jeden jest bardziej wydajny od drugiego?

Would it be better to use

if x == 'val':
    pass
else:
Author: Dan Getz, 2015-06-24

7 answers

Za pomocą dis aby spojrzeć na kod bajtowy wygenerowany dla dwóch wersji:

not ==

  4           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 RETURN_VALUE   

!=

  4           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               3 (!=)
              9 RETURN_VALUE   
Ta ostatnia ma mniej operacji, a zatem prawdopodobnie będzie nieco bardziej wydajna.

Zwrócono uwagę w Komendzie (Dzięki, @Quincunx ), że gdzie masz if foo != bar vs. if not foo == bar liczba operacji jest dokładnie taka sama, tylko że COMPARE_OP zmienia się i POP_JUMP_IF_TRUE przełączniki do POP_JUMP_IF_FALSE:

not ==:

  2           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_TRUE        16

!=

  2           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               3 (!=)
              9 POP_JUMP_IF_FALSE       16

W tym przypadku, o ile nie było różnicy w ilości pracy wymaganej dla każdego porównania, jest mało prawdopodobne, że w ogóle zauważysz różnicę wydajności.


Należy jednak pamiętać, że obie wersje nie zawsze będą logicznie identyczne , ponieważ będą zależeć od implementacji __eq__ i __ne__ dla danych obiektów. Na model danych dokumentacja :

Między operatorami porównania nie istnieją żadne implikowane relacje. Na prawda x==y nie oznacza, że x!=y jest fałszywa.

Na przykład:

>>> class Dummy(object):
    def __eq__(self, other):
        return True
    def __ne__(self, other):
        return True


>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True

Wreszcie, i być może najważniejsze: ogólnie, gdzie dwa logicznie identyczne, x != y jest znacznie bardziej czytelny niż not x == y.

 205
Author: jonrsharpe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:28

@jonrsharpe ma doskonałe wyjaśnienie tego, co się dzieje. Pomyślałem, że po prostu pokażę różnicę w czasie, gdy uruchamiam każdą z 3 opcji 10,000,000 razy (wystarczająco, aby pokazać niewielką różnicę).

Użyty kod:

def a(x):
    if x != 'val':
        pass


def b(x):
    if not x == 'val':
        pass


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


x = 1
for i in range(10000000):
    a(x)
    b(x)
    c(x)

I wyniki profilera cProfile:

Tutaj wpisz opis obrazka

Widzimy więc, że pomiędzy if not x == 'val': i if x != 'val': istnieje bardzo mała różnica wynosząca ~0,7%. Z nich if x != 'val': jest najszybszy.

Jednak, co najbardziej zaskakujące, widzimy, że

if x == 'val':
        pass
    else:

Jest w rzeczywistości najszybszy i bije if x != 'val': o ~0,3%. To nie jest zbyt czytelne, ale myślę, że jeśli chcesz nieznaczną poprawę wydajności, można pójść tą drogą.

 27
Author: Red Shift,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 13:33:55

W pierwszej z nich Python musi wykonać jeszcze jedną operację niż jest to konieczne(zamiast sprawdzać, czy nie jest równe, musi sprawdzić, czy nie jest prawdą, że jest równe, a więc jeszcze jedną operację). Nie da się odróżnić od jednego wykonania, ale jeśli uruchamiane wiele razy, drugie byłoby bardziej wydajne. Ogólnie użyłbym drugiego, ale matematycznie są takie same

 6
Author: JediPythonClone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 12:43:46
>>> from dis import dis
>>> dis(compile('not 10 == 20', '', 'exec'))
  1           0 LOAD_CONST               0 (10)
              3 LOAD_CONST               1 (20)
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT
             10 POP_TOP
             11 LOAD_CONST               2 (None)
             14 RETURN_VALUE
>>> dis(compile('10 != 20', '', 'exec'))
  1           0 LOAD_CONST               0 (10)
              3 LOAD_CONST               1 (20)
              6 COMPARE_OP               3 (!=)
              9 POP_TOP
             10 LOAD_CONST               2 (None)
             13 RETURN_VALUE

Tutaj widać, że not x == y mA o jedną instrukcję więcej niż x != y. Tak więc różnica w wydajności będzie bardzo mała w większości przypadków, chyba że robisz miliony porównań, a nawet wtedy prawdopodobnie nie będzie to przyczyną wąskiego gardła.

 5
Author: kylie.a,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 12:46:07

Dodatkowa uwaga, ponieważ inne odpowiedzi odpowiedziały na twoje pytanie w większości poprawnie, jest taka, że jeśli klasa definiuje tylko __eq__(), a nie __ne__(), to twoja COMPARE_OP (!=) uruchomi __eq__() i zaneguje to. W tym czasie trzecia opcja może być nieco bardziej wydajna, ale powinna być rozważana tylko wtedy, gdy potrzebujesz prędkości, ponieważ trudno ją szybko zrozumieć.

 5
Author: Jacob Zimmerman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 13:27:07

Chodzi o twój sposób czytania. not operator jest dynamiczny, dlatego możesz go zastosować w

if not x == 'val':

Ale != może być odczytany w lepszym kontekście jako operator, który robi odwrotnie niż ==.

 3
Author: Himanshu Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 12:50:04

Chcę rozszerzyć mój komentarz czytelności powyżej.

Ponownie, całkowicie zgadzam się z czytelnością nad innymi (wydajność-nieistotne) obawy.

Chciałbym zwrócić uwagę na to, że mózg interpretuje "pozytywne" szybciej niż"negatywne". Np. " stop "vs." do not go " (dość kiepski przykład ze względu na różnicę w liczbie słów).

Więc wybór:

if a == b
    (do this)
else
    (do that)

Jest lepsze od funkcjonalnie równoważnego:

if a != b
    (do that)
else
    (do this)

Mniej czytelność / zrozumiałość prowadzi do większej liczby błędów. Być może nie w początkowym kodowaniu, ale (nie tak inteligentny jak ty!) zmiany konserwacyjne...

 0
Author: Alan Jay Weiner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-01 13:24:37