Python `jeśli x nie jest żaden` lub` jeśli nie x jest żaden`?

745

Zawsze uważałem, że if not x is Nonewersja jest bardziej przejrzysta, ale zarówno przewodnik po stylu Google, jak i PEP-8if x is not None . Czy jest jakaś niewielka różnica w wydajności (zakładam, że nie) i czy jest jakikolwiek przypadek, w którym jedno naprawdę nie pasuje (co sprawia, że ​​drugi jest wyraźnym zwycięzcą mojej konwencji)? *

* Mam na myśli dowolny singleton, a nie tylko None.

... aby porównać singletony takie jak None. Zastosowanie jest lub nie jest.

orokusaki
źródło
8
is notjest operatorem sam w sobie. Jak !=. Jeśli wolisz, not x is Noneto należy również swoje wolą not a == bponad a != b.
Tomasz Gandor
@TomaszGandor Nie mam już tej opinii na temat not x is None(odpowiedzi tutaj mnie przekonały) - warto jednak zauważyć, że not a == bjest to preferowany styl w Pythonie w porównaniu do a != b.
orokusaki
4
@orokusaki to not a == bnaprawdę preferowany styl? Nigdy nie widziałem, aby robiono to w ten sposób i wszędzie wyglądam na ludzi, z których wszyscy korzystają !=.
Mike - SMT,
2
@orokusaki w Pythonie liczy się czytelność więc jest to preferowany styl użyć jednego operatora !=zamiast dwóch operatorów not, ==.
Jeyekomon

Odpowiedzi:

994

Nie ma różnicy w wydajności, ponieważ kompilują się do tego samego kodu bajtowego:

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Stylistycznie staram się unikać not x is y. Chociaż kompilator będzie zawsze traktował to jako not (x is y), ludzki czytelnik może źle zrozumieć konstrukcję jako (not x) is y. Jeśli piszę, x is not ynie ma dwuznaczności.

Daniel Stutzbach
źródło
103
Chyba że ten sam ludzki czytelnik tak myślał x is (not y). Ale zazwyczaj zgadzam się z tobą z innych powodów.
Etaoin
24
dodatkowo „nie jest” jest mniej dwuznaczne w tym kontekście „jeśli a nie jest Brak, a b to Brak:„ vs ”, jeśli nie jest to Brak, a b to Brak:”
Gordon Wrigley
45
operator powinien być „nie”
fasola
216

Zarówno Google, jak i przewodnik po stylu Python to najlepsza praktyka:

if x is not None:
    # Do something about x

Używanie not xmoże powodować niepożądane wyniki.

Patrz poniżej:

>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0]         # You don't want to fall in this one.
>>> not x
False

Możesz być zainteresowany tym, do których literałów są oceniane TrueFalse w Pythonie lub w:


Edytuj komentarz poniżej:

Właśnie wykonałem kilka testów. not x is Nonenie neguje xnajpierw, a potem w porównaniu do None. W rzeczywistości wydaje się, że isoperator ma wyższy priorytet, gdy jest używany w ten sposób:

>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False

Dlatego not x is Nonewłaśnie, moim zdaniem, najlepiej unikać.


Więcej edycji:

Właśnie wykonałem więcej testów i mogę potwierdzić, że komentarz bukzora jest prawidłowy. (Przynajmniej nie byłem w stanie udowodnić, że jest inaczej).

Oznacza to if x is not None, że ma dokładny wynik jak if not x is None. Poprawiono mnie. Dzięki bukzor.

Jednak moja odpowiedź nadal brzmi: użyj konwencjonalnegoif x is not None .:]

Xavier Ho
źródło
130

Kod powinien być napisany tak, aby był zrozumiały dla programisty, a na drugim - kompilator lub interpreter. Konstrukcja „nie jest” przypomina angielski bardziej niż „nie jest”.

Mark Ransom
źródło
33

Python if x is not Nonelub if not x is None?

TLDR: Kompilator kodu bajtowego analizuje je oba x is not None- więc ze względu na czytelność użyj if x is not None.

Czytelność

Używamy Pythona, ponieważ cenimy takie rzeczy, jak czytelność dla człowieka, użyteczność i poprawność różnych paradygmatów programowania nad wydajnością.

Python optymalizuje czytelność, szczególnie w tym kontekście.

Analiza i kompilacja kodu bajtowego

Że not wiąże się słabiej niżis , więc nie ma tu różnicy logicznej. Zobacz dokumentację :

Operatorzy isiis not test tożsamości obiektu: x is yjest prawdą, jeśli i tylko wtedy, gdy xiy są tym samym obiektem. x is not ydaje odwrotną wartość prawdy.

Jest is notto specjalnie przewidziane w Pythonie gramatyce jako poprawa czytelności dla języka:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

Jest to więc również element gramatyki.

Oczywiście nie jest tak samo parsowane:

>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"

Ale wtedy kompilator bajtów faktycznie przetłumaczy not ... isnais not :

>>> import dis
>>> dis.dis(lambda x, y: x is not y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Więc ze względu na czytelność i używanie języka zgodnie z przeznaczeniem, proszę użyć is not .

Nie używać tego nie jest mądre.

Aaron Hall
źródło
notPowiązania są słabsze niż is, więc nie ma tutaj logicznej różnicy” - z wyjątkiem tego, że Python nie musi wymuszać tożsamości logicznej i algebraicznej (nie ma wewnętrznego powodu, (1 + 2)*3aby oceniać to samo 1*3 + 2*3). Tutaj najwyraźniej Python oszukuje i optymalizuje UNARY_NOT.
Alexey
30

Odpowiedź jest prostsza niż ludzie.

W każdym razie nie ma przewagi technicznej, a „x nie jest y” jest tym, czego wszyscy inni używają , co czyni go wyraźnym zwycięzcą. Nie ma znaczenia, że ​​„wygląda bardziej jak angielski” czy nie; wszyscy go używają, co oznacza, że ​​każdy użytkownik Pythona - nawet chińscy, których język Python nie przypomina - na pierwszy rzut oka zrozumie, gdzie nieco mniej powszechna składnia zajmie kilka dodatkowych cykli mózgowych.

Nie bądź inny tylko dlatego, że jesteś inny, przynajmniej w tej dziedzinie.

Glenn Maynard
źródło
11

is notOperatora jest bardziej korzystny niż negując wyniku isprzyczyn historycznych. „ if x is not None:” czyta podobnie jak angielski, ale „ if not x is None:” wymaga zrozumienia pierwszeństwa operatora i nie czyta jak po angielsku.

Jeśli jest różnica w wydajności, moje pieniądze są na is not, ale prawie na pewno nie jest to motywacja do decyzji o preferowaniu tej techniki. Oczywiście byłoby to zależne od implementacji. Ponieważ isnie można go zastąpić, optymalizacja jakiegokolwiek rozróżnienia powinna być łatwa.

Mike Graham
źródło
9

Osobiście używam

if not (x is None):

który jest rozumiany natychmiastowo bez dwuznaczności przez wszystkich programistów, nawet tych, którzy nie są ekspertami w składni języka Python.

MikeTeX
źródło
5
Sprawiedliwy argument, z którym się zgadzam, ale uważam, że argument dotyczący idiomatycznego stylu jest silniejszy.
clacke,
2

if not x is Nonejest bardziej podobny do innych języków programowania, ale if x is not Nonezdecydowanie brzmi dla mnie wyraźniej (i jest bardziej poprawny gramatycznie w języku angielskim).

To powiedziawszy, wydaje mi się, że jest to dla mnie bardziej preferencja.

Davy8
źródło
0

Wolałbym bardziej czytelną formę x is not y niż myślałem, jak w końcu napisać pierwszeństwo obsługi kodu operatorów, aby uzyskać znacznie bardziej czytelny kod.

stefanogreg
źródło