Mam program w języku Python, w którym dwie zmienne są ustawione na wartość 'public'
. W wyrażeniu warunkowym mam porównanie, var1 is var2
które się nie udaje, ale jeśli je zmienię var1 == var2
, zwraca True
.
Teraz, jeśli otworzę mój interpreter Pythona i zrobię to samo porównanie „jest”, to się powiedzie.
>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True
Czego tu brakuje?
input = raw_input("Decide (y/n): ")
. : W takim przypadku wprowadzenie „y” iif input == 'y':
zwróci „True”, aif input is 'y':
zwróci False.Odpowiedzi:
is
jest testowanie tożsamości,==
to testowanie równości. to, co dzieje się w twoim kodzie, byłoby emulowane w interpretera w następujący sposób:nic więc dziwnego, że nie są takie same, prawda?
Innymi słowy:
is
jestid(a) == id(b)
źródło
==
vs.equals()
w Javie. Najlepsze jest to, że Python==
nie jest analogiczny do Javy==
.None
wartość. Więc zawsze ma ten sam identyfikator.Inne odpowiedzi tutaj są poprawne:
is
służy do porównania tożsamości , natomiast==
służy do porównania równości . Ponieważ zależy Ci na równości (dwa ciągi powinny zawierać te same znaki), w tym przypadkuis
operator jest po prostu zły i powinieneś używać==
zamiast tego.Przyczyną
is
tego jest interakcja polegająca na tym, że (większość) literałów łańcuchowych jest domyślnie internowana . Z Wikipedii:Tak więc, jeśli masz w programie dwa literały łańcuchowe (słowa, które są dosłownie wpisane do kodu źródłowego programu, otoczone znakami cudzysłowu), które mają tę samą wartość, kompilator Python automatycznie internalizuje ciągi znaków, dzięki czemu oba są przechowywane w tym samym miejscu lokalizacja pamięci. (Pamiętaj, że nie zawsze tak się dzieje, a zasady, kiedy to się dzieje, są dość skomplikowane, więc proszę nie polegać na tym zachowaniu w kodzie produkcyjnym!)
Ponieważ w sesji interaktywnej oba ciągi są faktycznie przechowywane w tej samej lokalizacji pamięci, mają tę samą tożsamość , więc
is
operator działa zgodnie z oczekiwaniami. Ale jeśli skonstruujesz ciąg za pomocą innej metody (nawet jeśli ten ciąg zawiera dokładnie takie same znaki), wówczas ciąg może być równy , ale nie jest to ten sam ciąg - to znaczy ma inną tożsamość , ponieważ jest przechowywane w innym miejscu w pamięci.źródło
==
iis
na podstawie tego, jaki rodzaj czeku chcesz. Jeśli zależy ci na równości łańcuchów (czyli o tej samej zawartości), zawsze powinieneś używać==
. Jeśli zależy ci na tym, czy jakieś dwie nazwy Python odnoszą się do tej samej instancji obiektu, powinieneś użyćis
. Możesz potrzebować,is
jeśli piszesz kod, który obsługuje wiele różnych wartości, nie troszcząc się o ich zawartość, lub jeśli wiesz, że jest tylko jedna z nich i chcesz zignorować inne obiekty, które podają się za takie rzeczy. Jeśli nie jesteś pewien, zawsze wybieraj==
.Słowo
is
kluczowe jest testem tożsamości obiektu podczas==
stanowi porównanie wartości.Jeśli użyjesz
is
, wynik będzie prawdziwy tylko wtedy, gdy obiekt jest tym samym obiektem. Jednak==
będzie prawdziwe każdym razem wartości obiektu są takie same.źródło
Na koniec należy zwrócić uwagę na tę
sys.intern
funkcję, aby upewnić się, że otrzymujesz odwołanie do tego samego ciągu:Jak wskazano powyżej, nie należy używać
is
do określania równości ciągów. Ale może to być pomocne, jeśli masz jakieś dziwne wymagania dotyczące używaniais
.Zauważ, że
intern
funkcja była wbudowana w Python 2, ale została przeniesiona dosys
modułu w Python 3.źródło
is
to testowanie tożsamości,==
to testowanie równości. Oznacza to, żeis
jest to sposób na sprawdzenie, czy dwie rzeczy są takie same lub po prostu równoważne.Powiedz, że masz prosty
person
przedmiot. Jeśli nazywa się „Jack” i ma „23” lat, jest to odpowiednik innego 23-letniego Jacka, ale nie jest to ta sama osoba.Są w tym samym wieku, ale nie są tym samym przykładem osoby. Ciąg może być równoważny z innym, ale nie jest to ten sam obiekt.
źródło
jack1.age = 99
, to się nie zmienijack2.age
. To dlatego, że są to dwa różne wystąpienia, więcjack1 is not jack2
. Mogą jednak być sobie równi,jack1 == jack2
jeśli ich nazwisko i wiek są takie same. To staje się bardziej skomplikowane dla ciągów, ponieważ ciągi są niezmienne w Pythonie, a Python często używa tej samej instancji. Podoba mi się to wyjaśnienie, ponieważ używa prostych przypadków (zwykły obiekt), a nie specjalnych przypadków (ciągów).To jest notatka poboczna, ale w pythonie idiomatycznym często zobaczysz takie rzeczy jak:
Jest to bezpieczne, ponieważ gwarantowana jest jedna instancja obiektu zerowego (tj. Brak) .
źródło
Jeśli nie masz pewności, co robisz, użyj „==”. Jeśli masz trochę więcej wiedzy na ten temat, możesz użyć „jest” dla znanych obiektów, takich jak „Brak”.
W przeciwnym razie będziesz się zastanawiać, dlaczego coś nie działa i dlaczego tak się dzieje:
Nie jestem nawet pewien, czy pewne rzeczy pozostaną takie same między różnymi wersjami / implementacjami Pythona.
źródło
Z mojego ograniczonego doświadczenia w Pythonie,
is
służy do porównywania dwóch obiektów, aby sprawdzić, czy są one tym samym obiektem, w przeciwieństwie do dwóch różnych obiektów o tej samej wartości.==
służy do ustalenia, czy wartości są identyczne.Oto dobry przykład:
s1
jest ciągiem Unicode is2
jest ciągiem normalnym. Nie są tego samego typu, ale mają tę samą wartość.źródło
Myślę, że ma to związek z faktem, że gdy porównanie „jest” daje w wyniku fałsz, używane są dwa różne obiekty. Jeśli ma wartość true, oznacza to, że wewnętrznie używa tego samego dokładnego obiektu i nie tworzy nowego, być może dlatego, że utworzyłeś je w ułamku około 2 sekund i ponieważ nie ma dużej przerwy między zoptymalizowanym a używa tego samego obiektu.
Dlatego powinieneś używać operatora równości
==
, a nieis
do porównywania wartości obiektu łańcuchowego.W tym przykładzie stworzyłem s2, który był innym obiektem łańcuchowym poprzednio równym „jeden”, ale nie jest to ten sam obiekt
s
, ponieważ, ponieważ interpreter nie używał tego samego obiektu, ponieważ początkowo nie przypisałem go do „jednego”, gdybym miał, uczyniłby z nich ten sam przedmiot.źródło
.replace()
jako przykładu w tym kontekście prawdopodobnie nie jest najlepsze, ponieważ jego semantyka może być myląca.s2 = s2.replace()
będzie zawsze utworzyć nowy obiekt string, przypisać do nowego obiektu ciągs2
, a następnie rozporządzania przedmiotem strun, któres2
wykorzystywane do punktu celu. Więc nawet gdybyś to zrobiłs = s.replace('one', 'one')
, nadal dostaniesz nowy obiekt łańcucha.Wierzę, że jest to znane jako ciągi „internowane”. Python to robi, podobnie jak Java, podobnie jak C i C ++ podczas kompilacji w trybach zoptymalizowanych.
Jeśli użyjesz dwóch identycznych łańcuchów, zamiast marnować pamięć, tworząc dwa obiekty łańcuchowe, wszystkie łańcuchy wewnętrzne o tej samej zawartości wskazują na tę samą pamięć.
Powoduje to, że operator „jest” w Pythonie zwraca wartość True, ponieważ dwa ciągi o tej samej zawartości wskazują ten sam obiekt ciągu. Stanie się tak również w Javie i C.
Jest to przydatne tylko w celu oszczędzania pamięci. Nie można na nim polegać w celu sprawdzenia równości łańcuchów, ponieważ różne interpretery i kompilatory oraz silniki JIT nie zawsze mogą to zrobić.
źródło
Odpowiadam na pytanie, mimo że pytanie jest stare, ponieważ żadna z powyższych odpowiedzi nie cytuje odniesienia do języka
W rzeczywistości operator sprawdza tożsamość, a operator == sprawdza równość,
Z języka odniesienia:
Typy wpływają na prawie wszystkie aspekty zachowania obiektu. W pewnym sensie ma to wpływ nawet na znaczenie tożsamości obiektu: w przypadku typów niezmiennych operacje obliczające nowe wartości mogą faktycznie zwracać odwołanie do dowolnego istniejącego obiektu o tym samym typie i wartości, podczas gdy w przypadku obiektów zmiennych jest to niedozwolone . Np. Po a = 1; b = 1, aib mogą, ale nie muszą odnosić się do tego samego obiektu o wartości jeden, w zależności od implementacji, ale po c = []; d = [], c id gwarantują, że odnoszą się do dwóch różnych, unikalnych, nowo utworzonych pustych list. (Zauważ, że c = d = [] przypisuje ten sam obiekt do c i d.)
dlatego z powyższego stwierdzenia możemy wywnioskować, że ciągi, które są niezmiennym typem, mogą zawieść, gdy są sprawdzane za pomocą „is” i mogą sprawdzać się, gdy sprawdzane za pomocą „is”
To samo dotyczy int, tuple, które są również typami niezmiennymi
źródło
==
Operatora Wartość testu równoważności.is
Tożsamość testy operator obiektu, testy Python czy te dwa są naprawdę ten sam obiekt (czyli na żywo pod tym samym adresem w pamięci).W tym przykładzie Python utworzył tylko jeden obiekt łańcuchowy i oba,
a
ib
odnosi się do niego. Powodem jest to, że Python wewnętrznie buforuje i ponownie wykorzystuje niektóre ciągi jako optymalizację, tak naprawdę w pamięci jest tylko ciąg „banan”, współdzielony przez a i b; Aby wyzwolić normalne zachowanie, musisz użyć dłuższych ciągów:Kiedy tworzysz dwie listy, otrzymujesz dwa obiekty:
W tym przypadku powiedzielibyśmy, że dwie listy są równoważne, ponieważ mają te same elementy, ale nie identyczne, ponieważ nie są tym samym obiektem. Jeśli dwa obiekty są identyczne, są również równoważne, ale jeśli są równoważne, niekoniecznie są identyczne.
Jeśli
a
odnosi się do obiektu, a ty przypisujeszb = a
, wówczas obie zmienne odnoszą się do tego samego obiektu:źródło
is
porówna lokalizację pamięci. Służy do porównywania na poziomie obiektu.==
porówna zmienne w programie. Służy do sprawdzania na poziomie wartości.is
sprawdza równoważność poziomu adresu==
sprawdza równoważność poziomu wartościźródło
is
to testowanie tożsamości,==
to testowanie równości (patrz Dokumentacja Pythona ).W większości przypadków, jeśli
a is b
, toa == b
. Ale są wyjątki, na przykład:Tak więc możesz używać tylko
is
do testów tożsamości, nigdy testów równości.źródło