Czy istnieje różnica między „= =” a „jest”?


Mój

Google-fu
https://english.stackexchange. ... -mean
nie dla mnie.
Czy w Pythonie poniższe dwa testy równości są równoważne?
n = 5
# Test one.
if n == 5:
print 'Yay!'# Test two.
if n is 5:
print 'Yay!'

Czy jest to prawdą w przypadku obiektów, w których można porównać wystąpienia (np.
lista
)?
Oto odpowiedź na moje pytanie:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...if L is [1]:
print 'Yay!'
# Doesn't.

Czyli wartość
==
tests, gdzie
to
testy, aby sprawdzić, czy są to ten sam obiekt?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

is
zwróci wartość
True
, jeśli dwie zmienne wskazują ten sam obiekt,
==
, jeśli obiekty, do których odwołują się zmienne, są równe.
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True# Make a new copy of list `a` via the slice operator,
# and assign it to variable `b`
>>> b = a[:]
>>> b is a
False
>>> b == a
True

W twoim przypadku drugi test działa tylko dlatego, że Python buforuje małe obiekty całkowite, co jest szczegółem implementacji. W przypadku dużych liczb całkowitych to nie działa:
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True

To samo dotyczy literałów ciągów:
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True

Przeczytaj również

to pytanie
https://coderoad.ru/26595/
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Istnieje prosta praktyczna zasada, która podpowiada, kiedy użyć
==
lub
is
.
  • ==
    jest dla równość wartości ... Użyj go, jeśli chcesz wiedzieć, czy dwa obiekty mają to samo znaczenie.
  • is
    - for równość wzorców ... Użyj go, jeśli chcesz wiedzieć, czy dwa odwołania odnoszą się do tego samego obiektu.

Ogólnie rzecz biorąc, kiedy 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ść 2 (
==
), a nie to, że
x
odnosi się dosłownie do tego samego obiektu co 2.
Jeszcze jedna uwaga, ze względu na sposób działania implementacji referencyjnej CPythona, otrzymasz nieoczekiwane i sprzeczne wyniki, jeśli omyłkowo użyjesz
is
do porównania równości referencji z liczbami całkowitymi:
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False

Dokładnie tego się spodziewaliśmy:
a
i
b
mają to samo znaczenie, ale są różnymi jednostkami. Ale co z tym?
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True

Jest to niezgodne z poprzednim wynikiem. Co tu się dzieje? Okazuje się, że implementacja Pythona, do której się odwołujemy, buforuje obiekty całkowite z zakresu -5..256 jako pojedyncze instancje ze względu na wydajność. Oto przykład, aby to zademonstrować:
>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));... 
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False

Jest to kolejny oczywisty powód, aby nie używać
is
: zachowanie pozostaje do zaimplementowania, gdy omyłkowo użyjesz go do równości wartości.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Czy jest różnica między
==
a
is
w Pythonie?
>Tak, mają bardzo ważną różnicę.
==
: test równości - semantyka polega na tym, że równoważne obiekty (które niekoniecznie są tym samym obiektem) będą testowane jako równe. w jaki sposób

tak jest napisane w dokumentacji
https://docs.python.org/3/refe ... isons
:

Operatory & <, & >, ==, & > =, & < = i nie tylko! = Porównaj wartości dwóch obiektów.

is
: semantyka sprawdzania tożsamości polega na tym, że obiekt (przechowywany w pamięci)

jest

obiekt. Ponownie w

dokumentacja mówi
https://docs.python.org/3/refe ... s-not
: :

Instrukcje
is
i
is
sprawdzają tożsamość obiektu:
x is y
is true
wtedy i tylko wtedy, gdy
x
i
y
to ten sam obiekt. Tożsamość obiektu to
jest zdefiniowana za pomocą funkcji
id ()
.
x is not y
daje odwrotny wynik
wartość prawdy.

Dlatego sprawdzanie tożsamości jest tym samym, co sprawdzanie równości identyfikatorów obiektów. To znaczy,
a is b

to jest to samo co:
id(a) == id(b)

gdzie
id
to wbudowana funkcja zwracająca liczbę całkowitą, która „gwarantuje unikalność wśród jednocześnie istniejących obiektów” (patrz
help (id)
) i gdzie
a
i
b
to dowolne obiekty.

Inne zastosowania
>
Powinieneś użyć tych porównań dla ich semantyki. Użyj
is
, aby sprawdzić tożsamość, i
==
, aby sprawdzić równość.
PEP 8, oficjalny przewodnik po stylu Pythona dla standardowej biblioteki również wspomina

dwa przypadki użycia dla
to
https://www.python.org/dev/pep ... tions
:

Porównania singletowe typu
None
powinny być zawsze dokonywane za pomocą
is
lub
is not
, nigdy operatorów równości.
Uważaj również na pisanie
if x
, kiedy naprawdę masz na myśli
jeśli x nie jest None
-
na przykład podczas sprawdzania, czy zmienna lub argument o wartości domyślnej
None
został ustawiony na inną wartość. Inna wartość może być typu (na przykład
jako kontener), co może być fałszywe w kontekście logicznym!


Definicje równości osobistej
>
Jeśli
is
jest true, to równość

zazwyczaj

można wywnioskować logicznie, jeśli obiekt jest sobą, to powinien zostać przetestowany jako równoważny samemu sobie.
W większości przypadków ta logika jest poprawna, ale opiera się na implementacji specjalnej metody
__eq__
. Jak mówią

lekarzy
https://docs.python.org/3/refe ... isons
,

Domyślne zachowanie dla porównań równości (
==
i
! =
) jest oparte na
tożsamość przedmiotów. Stąd porównanie równości instancji
z tą samą tożsamością prowadzi do równości i porównania równości
instancje z różnymi identyfikatorami powodują nierówności. Jeden
domyślną motywacją do tego zachowania jest pragnienie, aby wszystkie obiekty
musi być odblaskowy (tj. x-y implikuje x == y).

iw trosce o spójność rekomenduje:

Porównania równości powinny być refleksyjne. Innymi słowy, identyczne
obiekty muszą się równać:
x jest y
implikuje
x == y

Widzimy, że jest to domyślne zachowanie dla obiektów niestandardowych:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)

Zwykle jest również prawdą przeciwstawną - jeśli coś jest testowane jako nierówne, zwykle można wywnioskować, że nie jest to ten sam przedmiot.
Ponieważ testy równości można dostosowywać, wniosek ten nie zawsze jest prawdziwy dla wszystkich typów.

Wyjątek
>
Godnym uwagi wyjątkiem jest
nan
- zawsze testuje jako nierówny:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False

Sprawdzanie tożsamości może być znacznie szybszym sprawdzaniem niż sprawdzanie równości (co może wymagać rekurencyjnego sprawdzania członków).
Ale nie można tego zastąpić równością, gdy można znaleźć więcej niż jeden obiekt jako równoważny.
Zwróć uwagę, że porównanie równości między listami i krotkami zakłada, że ​​obiekty są identyczne (ponieważ jest to szybkie sprawdzenie). Może to powodować sprzeczności, jeśli logika jest niespójna - jak to się dzieje w przypadku
nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True


pouczająca historia:
>
Pytanie próbuje użyć
is
do porównania liczb całkowitych. Nie należy zakładać, że wystąpienie będące liczbą całkowitą jest tym samym wystąpieniem, co wystąpienie uzyskane z innego odwołania. Ta historia wyjaśnia, dlaczego.
Komentator miał kod, który opierał się na fakcie, że małe liczby całkowite (od -5 do 256 włącznie) są singletami w Pythonie, zamiast sprawdzać pod kątem równości.

Wow, może to prowadzić do podstępnych błędów. Miałem kod, który sprawdzał, czy b działa tak, jak chciałem, ponieważ aib to zwykle małe liczby. Błąd pojawił się dopiero dzisiaj, po sześciu miesiącach pracy, ponieważ a i b w końcu były na tyle duże, że nie można ich było buforować. - SHG

To działało podczas rozwoju. Być może przeszedł kilka testów jednostkowych.
I działał w produkcji - dopóki kod nie sprawdził liczby całkowitej większej niż 256, po czym nie udało się go wyprodukować.
Jest to usterka produkcyjna, która mogła zostać wykryta podczas przeglądania kodu lub przy użyciu narzędzia do sprawdzania stylu.
Podkreślę:
nie używaj
is
do porównywania liczb całkowitych.

https://stackoverflow.com/a/28864111/541136
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

==
określa, czy wartości są równe, a
is
określa, czy są to ten sam obiekt.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Jaka jest różnica między
is
a
==
?
>
==
i
is
to różne porównania! Jak powiedzieli inni:
  • ==
    porównuje wartości obiektów.
  • to
    porównuje odniesienia do obiektów.

W Pythonie nazwy odnoszą się do obiektów, na przykład w tym przypadku
value1
i
value2
odnoszą się do instancji
int
, która przechowuje wartość
1000
:
value1 = 1000
value2 = value1

https://i.stack.imgur.com/WLzXy.png
Ponieważ
value2
odnosi się do tego samego obiektu
is
, a
==
da
True
:
>>> value1 == value2
True
>>> value1 is value2
True

W poniższym przykładzie nazwy
value1
i
value2
odnoszą się do różnych wystąpień
int
, nawet jeśli oba zawierają tę samą liczbę całkowitą:
>>> value1 = 1000
>>> value2 = 1000

https://i.stack.imgur.com/IJgBI.png
Ponieważ ta sama wartość (liczba całkowita) jest przechowywana,
==
będzie
True
, dlatego często nazywa się to „porównaniem wartości”. Jednak
is
zwróci wartość
False
, ponieważ są to różne obiekty:
>>> value1 == value2
True
>>> value1 is value2
False


Kiedy i czego używać?
>
Zazwyczaj
is
to znacznie szybsze porównanie. Właśnie dlatego CPython buforuje (lub może lepiej użyć

re
) pewne obiekty, takie jak małe liczby całkowite, niektóre ciągi znaków itp. Ale to powinno być traktowane jako

Szczegóły dotyczące wdrożenia

które mogą (nawet jeśli jest to mało prawdopodobne) zmienić w dowolnym momencie bez ostrzeżenia.
Musisz

użyj tylko
is
,

Jeśli ty:
  • musisz sprawdzić, czy te dwa obiekty są w rzeczywistości tym samym obiektem (a nie tylko tą samą „wartością”). Jednym z przykładów może być używanie pojedynczego obiektu jako stałej.
  • chcesz porównać wartość z stały https://docs.python.org/library/constants.htmlPyton. Stałe w Pythonie to: [list][*]
    None
  • True
    <sup> 1 </sup>
  • False
    <sup> 1 </sup>
  • NotImplemented
  • Ellipsis
  • __debug__
  • klasy (np.
    int is int
    lub
    int is float
    )
  • mogą występować dodatkowe stałe w modułach wbudowanych lub modułach innych firm. na przykład
    np.ma.masked
    https://docs.scipy.org/doc/num ... askedz modułu NumPy)

[/*]
[/list]
W

w każdym innym przypadku należy użyć
==

do testowania równości.

Czy mogę dostosować zachowanie?
>
Jest jeszcze jeden aspekt
==
, o którym nie wspomniano wcześniej w innych odpowiedziach: to jest część

Pythons "Data model"
https://docs.python.org/3/refe ... el... Oznacza to, że jego zachowanie można dostosować za pomocą tej metody
__eq__
https://docs.python.org/refere ... __... Na przykład:
class MyClass(object):
def __init__(self, val):
self._value = val def __eq__(self, other):
print('__eq__ method called')
try:
return self._value == other._value
except AttributeError:
raise TypeError('Cannot compare {0} to objects of type {1}'
.format(type(self), type(other)))

To tylko sztuczny przykład ilustrujący, jak nazywa się ta metoda:
>>> MyClass(10) == MyClass(10)
__eq__ method called
True

Zwróć uwagę, że domyślnie (jeśli w klasie lub nadklasach nie ma innej implementacji
__eq__
)
__eq__
używa
is
:
class AClass(object):
def __init__(self, value):
self._value = value>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a

Dlatego tak naprawdę ważne jest, aby zaimplementować
__eq__
, jeśli chcesz mieć „więcej”, a nie tylko porównanie referencyjne dla niestandardowych klas!
Z drugiej strony nie można dostosować czeku
is
. Zawsze będzie porównywał

tylko

w przypadku, gdy masz ten sam link.

Czy te porównania zawsze zwracają wartość logiczną?
>
Ponieważ
__eq__
można ponownie zaimplementować lub nadpisać, nie ogranicza się do zwracania
True
lub
False
. To

mogą

zwraca cokolwiek (ale w większości przypadków powinno zwrócić wartość logiczną!).
Na przykład w przypadku tablic NumPy funkcja
==
zwróci tablicę:
>>> import numpy as np
>>> np.arange(10) == 2
array([False, False, True, False, False, False, False, False, False, False], dtype=bool)

Ale
to
True
False
lub czeki zawsze zwracają!
<sup>
1
</sup>
Jak wspomniał Aaron Hall w komentarzach:
Generalnie nie należy wykonywać żadnych kontroli
is True
lub
is False
, ponieważ te sprawdzenia są zwykle używane w kontekście, który niejawnie konwertuje

stan: schorzenie

na wartość logiczną (na przykład w instrukcji
if
). Zatem porównanie to
jest True

i

niejawne rzutowanie boolowskie wykonuje więcej pracy niż tylko rzutowanie boolowskie - i ograniczasz się do wartości logicznych (co nie jest uważane za pythonowe).
Jak wspomina PEP8:

Nie porównuj wartości logicznych z
True
lub
False
za pomocą
==
.
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Oni są

zupełnie inaczej
.
to
testuje tożsamość obiektu, podczas gdy
==
testuje równość (pojęcie zależne od typów dwóch operandów).
To po prostu szczęśliwy zbieg okoliczności, że „
is
” wydaje się działać poprawnie z małymi liczbami całkowitymi (np. 5 == 4 + 1). To dlatego, że

że CPython optymalizuje przechowywanie liczb całkowitych z zakresu (od -5 do 256), tworząc z nich pojedyncze
https://docs.python.org/2/c-ap ... ng... To zachowanie jest całkowicie zależne od implementacji i nie ma gwarancji, że będzie się utrzymywać we wszystkich rodzajach drobnych operacji transformacji.
Na przykład Python 3.5 również tworzy singlet z krótkich ciągów, ale ich cięcie przerywa to zachowanie:
>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

https://docs.python.org/librar ... isons
https://docs.python.org/librar ... isons
to
testy tożsamości
==
testy równości
Każda (mała) wartość całkowita jest mapowana na jedną wartość, więc wszystkie 3 są identyczne i równe. Jest to jednak szczegół implementacji, a nie część specyfikacji języka.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Twoja odpowiedź jest prawidłowa. Operator
is
porównuje tożsamość dwóch obiektów. Operator
==
porównuje wartości dwóch obiektów.
Tożsamość przedmiotu nigdy nie zmienia się po jego stworzeniu; możesz o nim myśleć jako o adresie obiektu w pamięci.
Możesz kontrolować zachowanie porównywania wartości obiektów, definiując metodę
__cmp__
lub

bogata metoda porównania
https://docs.python.org/refere ... ation
takie jak
__eq__
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Przyjrzyj się problemowi przepełnienia stosu
Operator „is” w Pythonie zachowuje się nieoczekiwanie w przypadku liczb całkowitych

https://coderoad.ru/306313/
liczby.
Zasadniczo sprowadza się to do tego, że „
is
” sprawdza, czy są to ten sam obiekt, a nie tylko sobie równe (liczby poniżej 256 to przypadek specjalny).
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

W skrócie,
is
sprawdza, czy dwa odniesienia wskazują na ten sam obiekt, czy nie.
==
sprawdza, czy dwa obiekty mają takie samo znaczenie, czy nie.
a=[1,2,3]
b=a #a and b point to the same object
c=list(a) #c points to different object if a==b:
print('#') #output:#
if a is b:
print('##') #output:##
if a==c:
print('###') #output:##
if a is c:
print('####') #no output as c and a point to different object
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jak powiedział John Feminella, przez większość czasu będziesz używać = = i! = Ponieważ Twoim celem jest porównanie wartości. Chciałbym tylko skategoryzować, co będziesz robić podczas odpoczynku:
Istnieje jedno i tylko jedno wystąpienie NoneType, to znaczy żadne z nich nie jest singletonem. Dlatego
foo == None
i
foo is None
oznaczają to samo. Jednak test
is
jest szybszy, a konwencją aktualizacji jest użycie
foo is None
.
Jeśli robisz jakąś introspekcję lub bawisz się przy usuwaniu elementów bezużytecznych lub sprawdzasz, czy Twój niestandardowy gadżet internowania ciągów działa, czy coś w tym stylu, prawdopodobnie masz przypadek użycia dla
foo
bar
.
True i False są również (teraz) singletami, ale nie ma przypadku użycia dla
foo == True
, a dla
foo jest True
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Różnica w Pythonie między is i equals (==)

Operator is może wydawać się taki sam jak operator równości, ale
to nie to samo.
Sprawdza, czy obie zmienne wskazują na ten sam obiekt, podczas gdy
sign = = sprawdza, czy wartości dwóch zmiennych są takie same.
Jeśli więc operator zwraca True, to równość jest zdecydowanie
To prawda, że ​​sytuacja odwrotna może być prawdą lub nie.

Oto przykład pokazujący podobieństwa i różnice.
>>> a = b = [1,2,3]
>>> c = [1,2,3]
>>> a == b
True
>>> a == c
True
>>> a is b
True
>>> a is c
False
>>> a = [1,2,3]
>>> b = [1,2]
>>> a == b
False
>>> a is b
False
>>> del a[2]
>>> a == b
True
>>> a is b
False
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Większość z nich już odpowiedziała na to pytanie. Jako dodatkowa uwaga (oparta na moim zrozumieniu i eksperymentach, ale nie z udokumentowanego źródła), oświadczenie

==, jeśli obiekty, do których odwołują się zmienne, są równe

z góry odpowiedzi należy czytać tak:

==, jeśli obiekty, do których odwołują się zmienne, są równe i należą do tego samego typu/klasy .

Doszedłem do tego wniosku na podstawie poniższego testu:
list1 = [1,2,3,4]
tuple1 = (1,2,3,4)print(list1)
print(tuple1)
print(id(list1))
print(id(tuple1))print(list1 == tuple1)
print(list1 is tuple1)

Tutaj zawartość listy i krotki jest taka sama, ale typ/klasa jest inny.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ponieważ inne osoby w tym poście odpowiadają szczegółowo na to pytanie, chciałbym

położyć nacisk

głównie porównanie między
is
a
==

na smyczki

co może dawać różne wyniki i zachęcałbym programistów do ostrożnego ich używania.
Aby porównać ciągi, użyj
==
zamiast
is
:
str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')

Z:
str is hello
str == hello


Ale

w poniższym przykładzie
==
i
is
dadzą różne wyniki:
str = 'hello sam'
if (str is 'hello sam'):
print ('str is hello sam')
if (str == 'hello sam'):
print ('str == hello sam')

Z:
str == hello sam


Wynik

:
Używaj
is
ostrożnie do porównań ciągów

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się