Porównaj, jeśli dwie zmienne odwołują się do tego samego obiektu w Pythonie

Odpowiedzi:

134

To isjest dla: x is yzwraca, Truejeśli xi ysą tym samym obiektem.

Jochen Ritzel
źródło
6
W tym przykładzie x is zzwraca False. Ale jeśli x i z mają przypisane te same wartości zamiast list (na przykład x, z = 13, 13), to x is zzwraca True. Dlaczego?
Bill
12
@Bill: To jest artefakt tego, jak Python obsługuje wartości int. Python przydziela obiekty będące liczbami całkowitymi, do których xi które zwskazują. Ponieważ małe liczby całkowite są typowe dla awarii (-1 jako wartość błędu, 0 za każdym razem, gdy coś faktycznie indeksujesz, małe liczby są zwykle rozsądnymi wartościami domyślnymi) .Python optymalizuje, wstępnie przydzielając małe liczby (od -5 do 256) i ponownie wykorzystuje ten sam obiekt typu integer. Zatem twój przykład działa tylko dla liczb z tego zakresu. Spróbuj przypisać coś większego, np 270. Aby uzyskać więcej informacji, zajrzyj tutaj
ted
1
@AndresR Nie, to źle. issprawdza, czy dwie nazwy odnoszą się do tej samej lokalizacji pamięci. Nie ma to nic wspólnego z samym przedmiotem. Łatwo jest mieć niezmienne obiekty, takie jak ciągi znaków, które są równe, ale nie są przechowywane w tym samym miejscu, na przykład ''a'*10000 is 'a' * 10000ma wartość False.
Jochen Ritzel
1
@JochenRitzel Masz całkowitą rację, dziękuję za ten komentarz! Więc nie rozumiem, co się dzieje "af" is "af"lub () is ()... dlaczego mają to samo miejsce w pamięci?
AndresR,
2
@AndreasR W przypadku literału ciągów / liczb w kodzie kompilator sprawdza, czy istnieją one tylko raz i ponownie je wykorzystuje. Specjalne wartości, takie jak (), None, True, False itp. Są również zdefiniowane jako pojedyncze. Podczas wykonywania środowisko wykonawcze również próbuje ponownie użyć małych liczb i ciągów, ale ostatecznie jest to kompromis między szybkością a pamięcią, a to, co się stanie, zależy od tego, jak zaimplementowano środowisko wykonawcze Pythona.
Jochen Ritzel
12

y is xbędzie True, y is zbędzie False.

Mark Rushakoff
źródło
11

Możesz także użyć id (), aby sprawdzić, do którego unikalnego obiektu odnosi się każda nazwa zmiennej.

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)
Rachunek
źródło
Uwaga @ teda na temat używania identyfikatora jest tutaj dość istotna.
Leo Ufimtsev
11

Podczas gdy dwa poprawne rozwiązania x is zi id(x) == id(z)zostały już wysłane, chcę podkreślić szczegółów wdrażania Pythona. Python przechowuje liczby całkowite jako obiekty, w ramach optymalizacji generuje na początku kilka małych liczb całkowitych (od -5 do 256) i wskazuje KAŻDĄ zmienną zawierającą liczbę całkowitą o małej wartości na te wstępnie zainicjowane obiekty. Więcej informacji

Oznacza to, że dla obiektów typu integer zainicjowanych na te same małe liczby (od -5 do 256) sprawdzenie, czy dwa obiekty są takie same, zwróci wartość true ( ON C-Pyhon , o ile wiem, jest to szczegół implementacji ), podczas gdy dla większych liczby zwraca to prawdę tylko wtedy, gdy jeden obiekt jest inicjowany z drugiego.

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True
przetrząsać
źródło
python3.6: a = 98765; b = 98765; a jest b => True. Coś najwyraźniej się zmieniło.
Michaił Kałasznikow
@MikhailKalashnikov Nope. Testowałem na Pythonie 3.6.2, to nadal istnieje.
nix
nadal istnieje na pythonie 3.7.7
Bill Huang
2

Bardzo lubię wizualną informację zwrotną, dlatego czasami po prostu otwieram http://www.pythontutor.com/visualize.html#mode=edit, aby zobaczyć, jak przydzielana jest pamięć i do czego się odwołuje.

wprowadź opis obrazu tutaj

Dodano ten niesamowity gif, ponieważ ta odpowiedź dotyczy wizualizacji ...

user1767754
źródło
2

To pochodzi z docs.python.org: „Każdy obiekt ma tożsamość, typ i wartość. Tożsamość obiektu nigdy się nie zmienia po jego utworzeniu; możesz myśleć o tym jako o adresie obiektu w pamięci. Operator„ is ” porównuje tożsamość dwóch obiektów; funkcja id () zwraca liczbę całkowitą reprezentującą jego tożsamość. "

Najwyraźniej za każdym razem, gdy zmieniasz wartość, obiekt jest odtwarzany, na co wskazuje zmiana tożsamości. Linia x = 3, po której następuje linia x = 3,14, nie daje błędu i podaje różne tożsamości, typy i wartości x.

Scott Woods
źródło
1
Doskonały chwyt doc.
prosti
xJest to nazwa identyfikacji obiektu z wartości z 3, a nie obiektu sama. Kiedy to zrobiłeś x=3.14, nie zmieniłeś obiektu, który był wcześniej identyfikowany x- zmieniłeś obiekt, do którego odnosiła się nazwa x .
ArtOfWarfare