„X nie w y” lub „nie x w y”

97

Podczas testowania członkostwa możemy użyć:

x not in y

Lub alternatywnie:

not x in y

Może istnieć wiele możliwych kontekstów dla tego wyrażenia w zależności od xi y. Może to dotyczyć na przykład sprawdzenia podciągów, członkostwa na liście, istnienia klucza dyktowania.

  • Czy te dwie formy są zawsze równoważne?
  • Czy istnieje preferowana składnia?
wim
źródło

Odpowiedzi:

112

Zawsze dają ten sam wynik.

W rzeczywistości not 'ham' in 'spam and eggs'wydaje się być specjalnie oznaczony wielkością liter, aby wykonać pojedynczą operację „nie w”, a nie operację „w”, a następnie zanegować wynik:

>>> import dis

>>> def notin():
    'ham' not in 'spam and eggs'
>>> dis.dis(notin)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not_in():
    not 'ham' in 'spam and eggs'
>>> dis.dis(not_in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not__in():
    not ('ham' in 'spam and eggs')
>>> dis.dis(not__in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

>>> def noteq():
    not 'ham' == 'spam and eggs'
>>> dis.dis(noteq)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 POP_TOP             
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE      

Na początku myślałem, że zawsze dawały ten sam wynik, ale sam notw sobie był po prostu logicznym operatorem negacji o niskim priorytecie, który można było zastosować a in btak samo łatwo jak każde inne wyrażenie logiczne, podczas gdy not inbył oddzielnym operatorem dla wygody i przejrzystości .

Demontaż powyżej był odkrywczy! Wygląda na to, że chociaż notjest to oczywiście operator logiczny negacji, formularz not a in bma specjalną wielkość liter, więc w rzeczywistości nie używa operatora ogólnego. Daje to not a in bdosłownie to samo wyrażenie a not in b, a nie tylko wyrażenie, które daje tę samą wartość.

Ben
źródło
4
Pamiętaj, że to tylko szczegół implementacji. Nie mogę nawet znaleźć wzmianki o not x in xsw dokumentacji.
phant0m
1
@ phant0m Absolutnie; sposób, w jaki powinieneś myśleć, not x in xsjest not (x in xs). Ale fakt, że jest implementowany przez parsowanie go do dokładnie tego samego kodu bajtowego, co x not in xsbardzo wyraźnie pokazuje, że muszą one być zawsze identyczne, w przeciwieństwie do rzeczy takich jak not x == yvs, x != yktóre powinny dawać ten sam wynik, ale nie muszą (w zależności od implementacji __eq__i __ne__zaangażowani).
Ben
11
Spróbuj uruchomić w CPython wizjer optymalizacji ; optymalizacja w czasie kompilacji, którą inne implementacje języka Python, takie jak Jython i IronPython, mogą swobodnie ignorować lub kopiować (nie jest to część specyfikacji języka).
Martijn Pieters
15

  1. Nie, nie ma różnicy.

    Operator not injest zdefiniowany tak, aby miał odwrotną wartość true równą in.

    - Dokumentacja Pythona

  2. Przypuszczam, że not injest to preferowane, ponieważ jest bardziej oczywiste i dodali do tego specjalny przypadek.

icktoofay
źródło
3

Inni już dali jasno do zrozumienia, że ​​te dwa stwierdzenia są, na dość niskim poziomie, równoważne.

Jednak nie sądzę, aby ktokolwiek jeszcze wystarczająco podkreślił, że skoro to pozostawia wybór Tobie, powinieneś

wybierz formę, która zapewni jak największą czytelność Twojego kodu.

I niekoniecznie tak czytelne, jak to tylko możliwe dla każdego , nawet jeśli jest to oczywiście fajna rzecz do osiągnięcia. Nie, upewnij się, że kod jest dla Ciebie możliwie jak najbardziej czytelny , ponieważ najprawdopodobniej wrócisz do tego kodu później i spróbujesz go przeczytać.

Tomas Aschan
źródło
Jeśli pracujesz w dużym zespole lub nad kodem, który prawdopodobnie pozostanie nietknięty przez jakiś czas, może być bardziej prawdopodobne, że ktoś inny będzie musiał go obsługiwać.
Tommy Herbert,
2

W Pythonie nie ma różnicy. I nie ma preferencji.

Ignacio Vazquez-Abrams
źródło
1

Składniowo są tym samym stwierdzeniem. Chciałbym szybko stwierdzić, że 'ham' not in 'spam and eggs'przekazuje jaśniejszy zamiar, ale widziałem kod i scenariusze, w których not 'ham' in 'spam and eggs'przekazuje jaśniejsze znaczenie niż inne.

Makoto
źródło