W komentarzu do tego pytania widziałem stwierdzenie, które zaleca użycie
result is not None
vs
result != None
Zastanawiałem się, na czym polega różnica i dlaczego jedno może być polecane bardziej niż drugie?
W komentarzu do tego pytania widziałem stwierdzenie, które zaleca użycie
result is not None
vs
result != None
Zastanawiałem się, na czym polega różnica i dlaczego jedno może być polecane bardziej niż drugie?
Odpowiedzi:
==
jest testem równości . Sprawdza, czy z prawej strony i lewa strona są równe obiektów (zgodnie z ich__eq__
lub__cmp__
metod).is
jest testem tożsamości . Sprawdza, czy prawa i lewa strona są tym samym przedmiotem. Nie są wykonywane żadne wywołania metod, obiekty nie mogą wpływać nais
operację.Używasz
is
(iis not
) do singletonów, np.None
Tam, gdzie nie przejmujesz się przedmiotami, które mogłyby udawać, żeNone
jesteś lub gdzie chcesz chronić przed pękaniem przedmiotów podczas porównywaniaNone
.źródło
None
ma kilka metod i prawie żadnych atrybutów. Jeśli__eq__
test oczekiwał metody lub atrybutu, może się on nie powieść.def __eq__( self, other ): return self.size == other.size
. Na przykład pęknie, jeśliother
tak się stanieNone
.is
jest jak Java==
. Python's==
jest jak Java.equals()
. Oczywiście pomaga to tylko wtedy, gdy znasz Javę.is
jest podobny===
(bardzo równy) i odwrotnieis not
jest podobny!==
(nie do końca równy).is not
to pojedynczy operator, czy po prostu neguje wynikis
podobny do wewnętrznegonot foo is bar
?Najpierw pozwól mi przejść przez kilka terminów. Jeśli chcesz tylko uzyskać odpowiedź na pytanie, przewiń w dół do „Odpowiedzi na pytanie”.
Definicje
Tożsamość obiektu : Kiedy tworzysz obiekt, możesz przypisać go do zmiennej. Następnie możesz przypisać ją do innej zmiennej. I kolejny.
W tym przypadku
cancel
,close
idismiss
wszystkie odnoszą się do tego samego obiektu w pamięci. Utworzyłeś tylko jedenButton
obiekt, a wszystkie trzy zmienne odnoszą się do tego jednego obiektu. Mówimy, żecancel
,close
idismiss
wszystkie odnoszą się do identycznych obiektów; to znaczy odnoszą się do jednego obiektu.Równość obiektów : porównując dwa obiekty, zwykle nie przejmujesz się, że odnosi się to dokładnie do tego samego obiektu w pamięci. Dzięki równości obiektów możesz zdefiniować własne reguły porównywania dwóch obiektów. Kiedy piszesz
if a == b:
, zasadniczo mówiszif a.__eq__(b):
. Umożliwia to zdefiniowanie__eq__
metody,a
dzięki czemu można użyć własnej logiki porównywania.Uzasadnienie porównań równości
Uzasadnienie: dwa obiekty mają dokładnie takie same dane, ale nie są identyczne. (Nie są tym samym obiektem w pamięci.) Przykład: Ciągi znaków
Uwaga: Używam tutaj ciągów znaków Unicode, ponieważ Python jest wystarczająco inteligentny, aby ponownie używać zwykłych ciągów bez tworzenia nowych w pamięci.
Tutaj mam dwa ciągi Unicode
a
ib
. Mają dokładnie taką samą treść, ale nie są tym samym obiektem w pamięci. Jednak porównując je, chcemy, aby były one równe. To, co się tutaj dzieje, polega na tym, że obiekt Unicode zaimplementował tę__eq__
metodę.Uwaga:
__eq__
onunicode
jest zdecydowanie zaimplementowany bardziej wydajnie niż to.Uzasadnienie: Dwa obiekty mają różne dane, ale są uważane za ten sam obiekt, jeśli niektóre kluczowe dane są takie same. Przykład: większość typów danych modelu
Tutaj mam dwa monitory Dell
a
ib
. Mają tę samą markę i model. Nie mają one jednak tych samych danych ani nie są tym samym obiektem w pamięci. Jednak porównując je, chcemy, aby były one równe. W tym przypadku obiekt Monitor zaimplementował tę__eq__
metodę.Odpowiadając na twoje pytanie
Porównując do
None
, zawsze używajis not
. W Pythonie żaden nie jest singletonem - w pamięci jest tylko jedno jego wystąpienie.Porównując tożsamość , można to zrobić bardzo szybko. Python sprawdza, czy obiekt, do którego się odwołujesz, ma taki sam adres pamięci jak globalny obiekt None - bardzo, bardzo szybkie porównanie dwóch liczb.
Porównując równość , Python musi sprawdzić, czy twój obiekt ma
__eq__
metodę. Jeśli nie, bada każdą nadklasę szukającą__eq__
metody. Jeśli je znajdzie, Python go wywołuje. Jest to szczególnie złe, jeśli__eq__
metoda jest powolna i nie wraca natychmiast, gdy zauważy, że jest inny obiektNone
.Nie wdrożyłeś
__eq__
? Wówczas Python prawdopodobnie znajdzie__eq__
metodęobject
i zastosuje ją zamiast tego - i tak po prostu sprawdza tożsamość obiektu.Porównując większość innych rzeczy w Pythonie, będziesz używać
!=
.źródło
Rozważ następujące:
źródło
None
jest singletonem, dlatego porównanie tożsamości zawsze będzie działać, podczas gdy obiekt może sfałszować porównanie równości za pomocą.__eq__()
.źródło
None
, ale niewłaściwe zachowanieNone
może wystąpić jako efekt uboczny wprowadzenia równości wobec innych typów. To nie tyle implikacje bezpieczeństwa, co implikacje poprawności.Niektóre obiekty są singletonami, a zatem
is
z nimi jest równoważne==
. Większość nie.źródło
()
i1
nie są z natury singletonami.-NSMALLNEGINTS <= n <= NSMALLPOSINTS
) i puste krotki są singletonami. Rzeczywiście nie jest to udokumentowane ani gwarantowane, ale raczej nie ulegnie zmianie.