is
Operator nie odpowiada wartości zmiennych, ale same instancje.
Co to naprawdę oznacza?
Zadeklarowałem dwie zmienne o nazwach x
i y
przypisaniu tych samych wartości w obu zmiennych, ale zwraca to fałsz, gdy używam is
operatora.
Potrzebuję wyjaśnienia. Oto mój kod.
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
Odpowiedzi:
Źle zrozumiałeś, co
is
testuje operator. Sprawdza, czy dwie zmienne wskazują ten sam obiekt , a nie, czy dwie zmienne mają tę samą wartość.Z dokumentacji dla
is
operatora :==
Zamiast tego użyj operatora:To drukuje
True
.x
iy
są to dwie osobne listy:Jeśli użyjesz
id()
funkcji , zobaczysz tox
iy
masz różne identyfikatory:ale jeśli miałbyś przypisać
y
do,x
to oba wskazują ten sam obiekt:i
is
pokazuje, że oba są tym samym obiektem, zwracaTrue
.Pamiętaj, że w Pythonie nazwy to tylko etykiety odwołujące się do wartości ; możesz mieć wiele nazw wskazujących na ten sam obiekt.
is
informuje, czy dwie nazwy wskazują na jeden i ten sam obiekt.==
informuje, czy dwie nazwy odnoszą się do obiektów o tej samej wartości.źródło
A is B
to to samo coid(A) == id(B)
.id(A)
w zmiennej i spodziewaszvariable == id(B)
się, że później nadal będzie działać; jeśliA
został w międzyczasie usunięty,B
mógł otrzymać to samo miejsce w pamięci.\n
>>> y = 5\n
>>> x jest y\n
Prawda\n
>>> x == y\n
Prawda\n
>>>\n
Inny duplikat pytał, dlaczego dwa równe ciągi generalnie nie są identyczne, na co tak naprawdę nie ma odpowiedzi:
Więc dlaczego nie są tym samym ciągiem? Szczególnie biorąc pod uwagę to:
Odłóżmy na chwilę drugą część. Jak pierwszy mógł być prawdziwy?
Interpreter musiałby mieć „tablicę interningową”, tabelę odwzorowującą wartości łańcuchowe na obiekty łańcuchowe, więc za każdym razem, gdy próbujesz utworzyć nowy łańcuch z zawartością
'abc'
, otrzymujesz ten sam obiekt. Wikipedia zawiera bardziej szczegółowe omówienie tego, jak działa staż.A Python ma tablicę umieszczania łańcuchów; możesz ręcznie internować ciągi za pomocą
sys.intern
metody.W rzeczywistości Python może automatycznie internować wszystkie niezmienne typy, ale nie jest to wymagane . Różne implementacje będą miały różne wartości.
CPython (implementacja, której używasz, jeśli nie wiesz, której implementacji używasz) auto-interns małe liczby całkowite i niektóre specjalne single, takie jak
False
, ale nie łańcuchy (lub duże liczby całkowite, małe krotki lub cokolwiek innego). Możesz to dość łatwo zobaczyć:OK, ale dlaczego były
z
iw
identyczne?To nie jest interpreter automatycznie internujący, to wartości składane kompilatora.
Jeżeli ten sam ciąg czasu kompilacji pojawia się dwa razy w tym samym module (co dokładnie oznacza to jest trudne do zdefiniowania, to nie to samo, co ciągiem znaków, ponieważ
r'abc'
,'abc'
i'a' 'b' 'c'
są różne literały ale ten sam ciąg, ale łatwe do zrozumienia intuicyjnie), kompilator utworzy tylko jedno wystąpienie ciągu z dwoma odwołaniami.W rzeczywistości kompilator może pójść nawet dalej:
'ab' + 'c'
może zostać przekonwertowany'abc'
przez optymalizator, w którym to przypadku może zostać złożony razem ze'abc'
stałą w tym samym module.Ponownie, jest to coś, co Python jest dozwolony, ale nie jest do tego zobowiązany. Ale w tym przypadku CPython zawsze składa małe łańcuchy (a także np. Małe krotki). (Chociaż kompilator instrukcji interpretera interaktywnego nie uruchamia takiej samej optymalizacji, jak kompilator modułu w czasie, więc nie zobaczysz dokładnie tych samych wyników interaktywnie).
Co więc powinieneś z tym zrobić jako programista?
Jak nic. Prawie nigdy nie masz powodu, by przejmować się, czy dwie niezmienne wartości są identyczne. Jeśli chcesz wiedzieć, kiedy możesz użyć
a is b
zamiasta == b
, zadajesz niewłaściwe pytanie. Po prostu zawsze używaja == b
z wyjątkiem dwóch przypadków:x is None
.x
wpłynie nay
.źródło
w
iz
są identyczne ze względu na składane wartości kompilatora, dlaczego działa to również w REPL, nawet używającid()
do sprawdzenia referencji? Korzystanie z REPL w Pythonie 3.7is
zwraca prawdę tylko wtedy, gdy są faktycznie tym samym obiektem. Gdyby były takie same, zmiana na jedną pojawiłaby się również w drugiej. Oto przykład różnicy.źródło
Gdy pojawi się zduplikowane pytanie , analogia może zadziałać:
źródło
is
iis not
są dwoma operatorami tożsamości w Pythonie.is
Operator nie porównuje wartości zmiennych, ale porównuje tożsamości zmiennych. Rozważ to:Powyższy przykład pokazuje, że tożsamość (może to być również adres pamięci w Cpythonie) jest różna dla obu
a
ib
(nawet jeśli ich wartości są takie same). Dlatego, gdy mówisza is b
, zwraca fałsz z powodu niedopasowania tożsamości obu operandów. Jednak gdy powiesza == b
, zwraca true, ponieważ==
operacja weryfikuje tylko wtedy, gdy oba operandy mają przypisaną tę samą wartość.Ciekawy przykład (za dodatkową ocenę):
W powyższym przykładzie, mimo
a
ib
są to dwie różne zmienne,a is b
zwróconeTrue
. Wynika to z faktu typua
Isint
która jest niezmienna obiekt. Więc python (myślę, że aby zaoszczędzić pamięć) przydzielił ten sam obiekt,b
gdy został utworzony z tą samą wartością. Tak więc w tym przypadku tożsamości zmiennych pasowały ia is b
okazały się takieTrue
.Będzie to miało zastosowanie do wszystkich niezmiennych obiektów:
Mam nadzieję, że to pomoże.
źródło
-5
lub wyższe niż256
w Pythonie będzie fałszywe. Python buforuje liczby w zakresie [-5, 256].x is y
to samo coid(x) == id(y)
porównywanie tożsamości przedmiotów.Jak zauważył @ tomasz-kurgan w komentarzu poniżej,
is
operator zachowuje się nietypowo w przypadku niektórych obiektów.Na przykład
Ref;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24
źródło
Jak możesz sprawdzić tutaj do małych liczb całkowitych. Liczby powyżej 257 nie są małymi intami, więc są obliczane jako inny obiekt.
W
==
takim przypadku lepiej jest użyć zamiast tego.Więcej informacji można znaleźć tutaj: http://docs.python.org/2/c-api/int.html
źródło
X wskazuje na tablicę, Y wskazuje na inną tablicę. Te tablice są identyczne, ale
is
operator przyjrzy się tym wskaźnikom, które nie są identyczne.źródło
is
pokazuje to funkcjonalność operatora.id
chyba że o to poprosisz.Porównuje tożsamość obiektu, to znaczy, czy zmienne odnoszą się do tego samego obiektu w pamięci. To jest jak
==
w Javie lub C (porównując wskaźniki).źródło
Prosty przykład z owocami
Wynik:
Jeśli spróbujesz
Wynik jest inny:
Dzieje się tak, ponieważ operator == porównuje tylko zawartość zmiennej. Aby porównać tożsamości dwóch zmiennych, użyj operatora is
Aby wydrukować numer identyfikacyjny:
źródło
is
Operator jest tylko wersja angielska==
. Ponieważ identyfikatory obu list są różne, odpowiedź jest fałszywa. Możesz spróbować:* Ponieważ identyfikatory obu list byłyby takie same
źródło
is
nie jest „angielską wersją==
”