Moje Google-fu mnie zawiodło.
Czy w Pythonie następujące dwa testy na równoważność są równoważne?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
Czy dotyczy to obiektów, w których porównywałbyś instancje ( list
powiedzmy)?
Okej, więc ten rodzaj odpowiedzi na moje pytanie:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
Więc ==
testy sprawdzają, gdzie is
testy sprawdzają, czy są one tym samym obiektem?
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
wyjście:False True False
.b = a[:]
częścią kopiującą listę operatorów wycinania, więc zredagowałem twoją odpowiedź, aby dodać komentarz. Wygląda na to, że właśnie osiągnąłem próg, aby nie musieć sprawdzać moich zmian przed ich zastosowaniem, więc mam nadzieję, że to fajnie. Niezależnie od tego, oto przydatne informacje na temat kopiowania list, które natknąłem się i musiałem odnieść się, aby dowiedzieć się, co robisz: stackoverflow.com/a/2612815/4561887==
. Tak5.0
na przykład, jest wartością zmiennoprzecinkową, a5
jest liczbą całkowitą. Ale5.0 == 5
nadal wróci,True
ponieważ reprezentują tę samą wartość. Pod względem wydajności i pisania kaczego,is
interpreter zawsze testuje, porównując adresy pamięci operandu, podczas gdy==
to od niego zależy, czy sam określi, czy definiuje się jako coś innego.1000 is 10**3
zwraca wartość True w Pythonie 3.7, ponieważ 10 ** 3 jest typemint
. Ale1000 is 1e3
ocenia na False, ponieważ 1e3 jest typemfloat
.1000 is 10**3
prawda jest prawdą, zależy od implementacji i zależy od kompilacji wstępnie oceniającej wyrażenie10**3
.x=10; 1000 is x**3
ocenia naFalse
.Istnieje prosta zasada, która mówi, kiedy użyć
==
lubis
.==
oznacza równość wartości . Użyj go, jeśli chcesz wiedzieć, czy dwa obiekty mają tę samą wartość.is
jest dla równości odniesienia . Użyj go, jeśli chcesz wiedzieć, czy dwa odniesienia odnoszą się do tego samego obiektu.Ogólnie rzecz biorąc, gdy porównujesz coś do prostego typu, zwykle sprawdzasz równość wartości , więc powinieneś użyć
==
. Na przykład, celem twojego przykładu jest prawdopodobnie sprawdzenie, czy x ma wartość równą 2 (==
), a niex
to, czy dosłownie odnosi się do tego samego obiektu co 2.Należy zwrócić uwagę na coś innego: ze względu na sposób działania implementacji referencji CPython otrzymasz nieoczekiwane i niespójne wyniki, jeśli omyłkowo użyjesz
is
do porównania równości referencji na liczbach całkowitych:To dość dużo, co można się spodziewać:
a
ib
mają taką samą wartość, ale są odrębnymi podmiotami. Ale co z tym?Jest to niezgodne z wcześniejszym wynikiem. Co tu się dzieje? Okazuje się, że referencyjna implementacja Pythona buforuje obiekty całkowite z zakresu -5..256 jako instancje singletonów ze względu na wydajność. Oto przykład, który to pokazuje:
To kolejny oczywisty powód, dla którego nie należy używać
is
: zachowanie należy do implementacji, gdy błędnie używa się go do równości wartości.źródło
a=500
ib=500
, chciałem tylko zauważyć, że jeśli ustawisza
ib
na interger między [-5, 256],a is b
faktycznie zwracaTrue
. Więcej informacji tutaj: stackoverflow.com/q/306313/7571052==
określa, czy wartości są równe, a jednocześnieis
określa, czy są dokładnie tym samym obiektem.źródło
Tak, mają bardzo ważną różnicę.
==
: sprawdź równość - semantyka polega na tym, że równoważne obiekty (niekoniecznie te same obiekty) będą testować jako równe. Jak mówi dokumentacja :is
: sprawdź tożsamość - semantyka polega na tym, że obiekt (przechowywany w pamięci) jest obiektem. Ponownie dokumentacja mówi :Zatem sprawdzenie tożsamości jest takie samo, jak sprawdzenie równości identyfikatorów obiektów. To jest,
jest taki sam jak:
gdzie
id
jest wbudowana funkcja, która zwraca liczbę całkowitą, która „gwarantuje, że jest unikalna wśród jednocześnie istniejących obiektów” (patrzhelp(id)
) oraz gdziea
ib
są dowolnymi obiektami.Inne wskazówki użytkowania
Powinieneś używać tych porównań dla ich semantyki. Służy
is
do sprawdzania tożsamości i==
równości.Ogólnie rzecz biorąc, używamy
is
do sprawdzania tożsamości. Jest to zwykle przydatne, gdy szukamy obiektu, który powinien istnieć tylko raz w pamięci, zwany w dokumentacji „singletonem”.Przypadki użycia
is
obejmują:None
Typowe przypadki użycia
==
obejmują:Ogólny przypadek użycia, znowu, dla
==
, jest przedmiotem chcesz nie może być taki sam przedmiot, a nie może być równoważny jedenKierunki PEP 8
PEP 8, oficjalny przewodnik po języku Python dla standardowej biblioteki, wspomina również o dwóch przypadkach użycia dla
is
:Wnioskowanie o równości na podstawie tożsamości
Jeśli
is
jest to prawda, równość zwykle można wywnioskować - logicznie, jeśli obiekt jest sam, to powinien on przetestować jako równoważny sam sobie.W większości przypadków ta logika jest prawdziwa, ale opiera się na implementacji
__eq__
specjalnej metody. Jak mówią doktorzy ,oraz w celu zachowania spójności zaleca:
Widzimy, że jest to domyślne zachowanie niestandardowych obiektów:
Przeciwne jest również zwykle prawda - jeśli coś nie jest równe, zwykle można wywnioskować, że nie są one tym samym przedmiotem.
Ponieważ testy równości można dostosować, wnioskowanie to nie zawsze jest prawdziwe dla wszystkich typów.
Wyjątek
Godnym uwagi wyjątkiem jest
nan
- zawsze testuje się jako nie równy sobie:Sprawdzanie tożsamości może być znacznie szybsze niż sprawdzanie równości (co może wymagać rekurencyjnego sprawdzania członków).
Ale nie można go zastąpić równością, w której można znaleźć więcej niż jeden obiekt jako równoważny.
Zauważ, że porównanie równości list i krotek zakłada, że tożsamość obiektów jest równa (ponieważ jest to szybka kontrola). Może to powodować sprzeczności, jeśli logika jest niespójna - tak jak w przypadku
nan
:Przestroga:
Pytanie próbuje użyć
is
do porównania liczb całkowitych. Nie należy zakładać, że wystąpienie liczby całkowitej jest tym samym wystąpieniem, co wystąpienie innego odwołania. Ta historia wyjaśnia, dlaczego.Komentator miał kod, który polegał na tym, że małe liczby całkowite (od -5 do 256 włącznie) są singletonami w Pythonie, zamiast sprawdzania równości.
Działało w rozwoju. Być może minęło trochę nieprzyzwoitych wydarzeń.
I działało w produkcji - dopóki kod nie sprawdził liczby całkowitej większej niż 256, w którym momencie nie powiodło się w produkcji.
Jest to błąd produkcyjny, który mógł zostać wykryty podczas przeglądania kodu lub ewentualnie za pomocą narzędzia sprawdzającego styl.
Podkreślę: nie używaj
is
do porównywania liczb całkowitych.źródło
is None
wyjątek, ale to powiedziawszy,== None
działa również ...is
do porównywaniaEnum
s.Jaka jest różnica między
is
i==
?==
iis
są różne porównania! Jak już powiedzieli inni:==
porównuje wartości obiektów.is
porównuje odniesienia do obiektów.W nazwach Python odnoszą się do obiektów, na przykład w tym przypadku
value1
ivalue2
odnoszą się doint
instancji przechowującej wartość1000
:Ponieważ
value2
odnosi się do tego samego obiektuis
i==
daTrue
:W kolejnym przykładzie nazwy
value1
ivalue2
odnosi się do innychint
przypadkach, nawet jeśli obie przechowywać ten sam całkowitą:Ponieważ przechowywana
==
będzie ta sama wartość (liczba całkowita)True
, dlatego często nazywa się ją „porównywaniem wartości”. Jednakis
wróci,False
ponieważ są to różne obiekty:Kiedy stosować który?
Ogólnie
is
jest to znacznie szybsze porównanie. Dlatego CPython buforuje (a może ponowne użycie byłoby lepszym terminem) niektóre obiekty, takie jak małe liczby całkowite, niektóre ciągi znaków itp. Ale to powinno być traktowane jako szczegół implementacji, który może (nawet jeśli jest to mało prawdopodobne) zmienić w dowolnym momencie bez ostrzeżenia.Powinieneś używać tylko,
is
jeśli:chcę porównać wartość ze stałą Python . Stałe w Pythonie to:
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
lubint is float
)np.ma.masked
z modułu NumPy)W każdym innym przypadku należy użyć
==
do sprawdzenia równości.Czy mogę dostosować zachowanie?
Jest pewien aspekt, o
==
którym nie wspomniano już w innych odpowiedziach: jest to część „modelu danych” Pythona . Oznacza to, że jego zachowanie można dostosować za pomocą tej__eq__
metody. Na przykład:To tylko sztuczny przykład ilustrujący, że metoda naprawdę nazywa się:
Zauważ, że domyślnie (jeśli nie
__eq__
można znaleźć innej implementacji w klasie lub nadklasach)__eq__
używais
:Dlatego tak naprawdę ważne jest wdrożenie,
__eq__
jeśli chcesz „więcej” niż tylko porównanie referencji dla klas niestandardowych!Z drugiej strony nie można dostosowywać
is
czeków. Zawsze będzie się porównywał tylko wtedy, gdy masz to samo odniesienie.Czy te porównania zawsze zwracają wartość logiczną?
Ponieważ
__eq__
można go ponownie wdrożyć lub zastąpić, nie ogranicza się do zwrotuTrue
lubFalse
. To mogło powrócić niczego (ale w większości przypadków należy zwrócić wartość logiczną!).Na przykład z tablicami NumPy
==
zwróci tablicę:Ale
is
czeki zawsze będą zwracaneTrue
lubFalse
!1 Jak wspomniał Aaron Hall w komentarzach:
Zasadniczo nie powinieneś wykonywać żadnych testów
is True
aniis False
kontroli, ponieważ zwykle używa się tych „kontroli” w kontekście, który domyślnie przekształca warunek na wartość logiczną (na przykład wif
instrukcji). Tak więcis True
porównanie i niejawna obsada boolean wymaga więcej pracy niż wykonanie obsady boolean - a ty ograniczasz się do booleanów (co nie jest uważane za pytoniczne).Jak wspomina PEP8:
źródło
is
- nazwami, które wskazują na logiczne wartości, należy sprawdzić w kontekście logicznym - jakif __debug__:
lubif not __debug__:
. Nigdy nie powinieneś robićif __debug__ is True:
aniif __debug__ == True:
- ponadto, stała jest jedynie stałą wartością semantyczną, a nie singletonem, dlatego sprawdzanieis
w tym przypadku nie jest semantycznie poprawne. Rzucam ci wyzwanie, byś znalazł źródło dla swoich twierdzeń - nie sądzę, żebyś je znalazł.None
,True
,False
i__debug__
to, co można by nazwać „stałej wartości semantycznej”, ponieważ nie mogą być przypisane. Ale wszystkie z nich są singletonami.is True
lubif False
sprawdź (ale tak, są one dość rzadkie - ale jeśli to zrobisz, możesz to zrobić za pomocąis
). Dlatego nawet CPython używa ich czasami (na przykład tutaj lub tutaj )Oni są zupełnie inni .
is
sprawdza tożsamość obiektu, a==
sprawdza równość (pojęcie, które zależy od typów dwóch operandów).To tylko szczęśliwy zbieg okoliczności, że „
is
” wydaje się działać poprawnie z małymi liczbami całkowitymi (np. 5 == 4 + 1). Jest tak, ponieważ CPython optymalizuje przechowywanie liczb całkowitych w zakresie (-5 do 256), czyniąc je singletonami . To zachowanie jest całkowicie zależne od implementacji i nie ma gwarancji, że zostanie zachowane we wszelkiego rodzaju drobnych operacjach transformacyjnych.Na przykład Python 3.5 tworzy także singletony krótkich ciągów, ale krojenie ich zakłóca takie zachowanie:
źródło
https://docs.python.org/library/stdtypes.html#comparisons
is
testy dla testów tożsamości==
dla równościKażda (mała) wartość całkowita jest odwzorowana na pojedynczą wartość, więc każda 3 jest identyczna i równa. Jest to szczegół implementacji, ale nie jest częścią specyfikacji języka
źródło
Twoja odpowiedź jest poprawna.
is
Operatora porównuje identyczności dwóch przedmiotów.==
Operatora porównuje wartości dwóch przedmiotów.Tożsamość obiektu nigdy się nie zmienia po utworzeniu; możesz myśleć o tym jako o adresie obiektu w pamięci.
Możesz kontrolować zachowanie porównawcze wartości obiektów, definiując
__cmp__
metodę lub bogatą metodę porównywania , taką jak__eq__
.źródło
Spójrz na pytanie o przepełnienie stosu Operator „jest” Pythona zachowuje się nieoczekiwanie przy liczbach całkowitych .
Sprowadza się to głównie do tego, że „
is
” sprawdza, czy są one tym samym obiektem, a nie tylko sobie równe (liczby poniżej 256 są szczególnym przypadkiem).źródło
W skrócie
is
sprawdza, czy dwa odwołania wskazują na ten sam obiekt, czy nie.==
sprawdza, czy dwa obiekty mają tę samą wartość, czy nie.źródło
Jak powiedział John Feminella, przez większość czasu będziesz używać == i! =, Ponieważ Twoim celem jest porównanie wartości. Chciałbym tylko podzielić na kategorie, co zrobiłbyś przez resztę czasu:
Istnieje jedna i tylko jedna instancja NoneType, tzn. None nie jest singletonem. W konsekwencji
foo == None
ifoo is None
znaczy to samo. Jednakis
test jest szybszy i należy użyć konwencji Pythonafoo is None
.Jeśli robisz jakieś introspekcji lub mucking ze zbierania śmieci lub sprawdzanie, czy zwyczaj wybudowany internowanie łańcuchów gadżet działa lub suchlike, a następnie prawdopodobnie masz przypadków użycia za
foo
tobar
.Prawda i fałsz są również (teraz) singletonami, ale nie ma przypadku
foo == True
użycia ani przypadku użyciafoo is True
.źródło
Większość z nich już odpowiedziała na ten temat. Podobnie jak dodatkowa uwaga (oparta na moim zrozumieniu i eksperymentach, ale nie z udokumentowanego źródła), oświadczenie
z powyższych odpowiedzi należy rozumieć jako
. Doszedłem do tego wniosku na podstawie poniższego testu:
Tutaj zawartość listy i krotki są takie same, ale typ / klasa są różne.
źródło
Różnica w Pythonie między jest i jest równa (==)
Oto przykład pokazujący podobieństwo i różnicę.
źródło
Ponieważ inne osoby w tym poście szczegółowo odpowiadają na pytanie, chciałbym przede wszystkim podkreślić porównanie między ciągami znaków
is
i==
dla nich, które mogą dawać różne wyniki, i zachęcam programistów do ich ostrożnego korzystania.Do porównania ciągów należy użyć
==
zamiastis
:Na zewnątrz:
Ale w poniższym przykładzie
==
iis
będzie uzyskać różne wyniki:Na zewnątrz:
Wniosek:
Użyj
is
ostrożnie, aby porównać ciągi znakówźródło