Есть ли разница между "==" и "есть"?
Мой Google-фу провалил меня.
В Python следующие два теста эквивалентны равенству?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
Сохраняет ли это значение для объектов, где вы будете сравнивать экземпляры (например, list
)?
Хорошо, так этот вопрос отвечает на мой вопрос:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
Так ==
значение тестов, где is
тесты, чтобы увидеть, если они тот же объект?
Ответы
Ответ 1
is
вернет True
если две переменные указывают на один и тот же объект, ==
если объекты, на которые ссылаются переменные, равны.
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True
>>> b = a[:] # Make a new copy of list 'a' via the slice operator, and assign it to variable 'b'
>>> b is a
False
>>> b == a
True
В вашем случае второй тест работает только потому, что Python кэширует небольшие целочисленные объекты, что является деталью реализации. Для больших целых чисел это не работает:
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
То же самое верно для строковых литералов:
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
Пожалуйста, смотрите этот вопрос также.
Ответ 2
Существует простое эмпирическое правило, когда вы можете использовать ==
или is
.
-
==
- для равенства значений. Используйте его, если хотите узнать, имеют ли два объекта одинаковое значение.
-
is
для ссылочного равенства. Используйте его, если хотите узнать, ссылаются ли на две ссылки на один и тот же объект.
В общем, когда вы сравниваете что-то с простым типом, вы обычно проверяете равенство значений, поэтому вы должны использовать ==
. Например, целью вашего примера является проверка того, имеет ли x значение, равное 2 (==
), а не то, что x
буквально ссылается на тот же объект, что и на 2.
Что-то еще следует отметить: из-за того, как работает эталонная реализация CPython, вы получите неожиданные и непоследовательные результаты, если вы ошибочно используете is
для сравнения для ссылочного равенства по целым числам:
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
Это в значительной степени то, что мы ожидали: a
и b
имеют одинаковое значение, но являются разными объектами. Но как насчет этого?
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
Это не соответствует предыдущему результату. Что здесь происходит? Оказалось, что эталонная реализация Python кэширует целые объекты в диапазоне -5,256 в качестве одноэлементных экземпляров по соображениям производительности. Вот пример, демонстрирующий это:
>>> 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
Это еще одна очевидная причина не использовать is
: поведение остается за реализацией, когда вы ошибочно используете его для равенства значений.
Ответ 3
==
определяет, является ли значения равны, в то время как is
определяет, если они точно такой же объект и равные.
Ответ 4
Есть ли разница между ==
и is
в Python?
Да, у них очень важная разница.
==
: проверка равенства - семантика состоит в том, что эквивалентные объекты (которые не обязательно являются одним и тем же объектом) будут проверяться как равные. Как говорится в документации:
Операторы <,>, ==,> =, <=, и! = Сравнивают значения двух объектов.
is
: check for identity - семантика is
в том, что объектом (как хранящимся в памяти) является объект. Опять же, в документации говорится:
Операторы is
и is not
проверяют идентификатор объекта: x is y
истинным тогда и только тогда, когда x
и y
являются одним и тем же объектом. Идентификатор объекта определяется с помощью функции id()
. x is not y
дает обратное значение истины.
Таким образом, проверка идентичности совпадает с проверкой равенства идентификаторов объектов. То есть,
a is b
такой же как:
id(a) == id(b)
где id
- встроенная функция, которая возвращает целое число, которое "гарантировано будет уникальным среди одновременно существующих объектов" (см. help(id)
) и где a
и b
- любые произвольные объекты.
Другие направления использования
Вы должны использовать эти сравнения для своей семантики. Используйте is
, чтобы проверить личность и ==
для проверки равенства.
PEP 8, официальный стиль руководства Python для стандартной библиотеки также упоминает два примеры использования для is
:
Сравнения одиночек как None
всегда должно быть сделано с is
или is not
, никогда не операторы равенства.
Кроме того, остерегайтесь писать, if x
когда вы действительно имеете в виду, if x is not None
- например, при проверке того, была ли переменная или аргумент, для которых по умолчанию выбрано значение None
было установлено какое-то другое значение. Другое значение может иметь тип (например, контейнер), который может быть ложным в булевом контексте!
Вывод равенства из тождества
Если is
is true, равенство обычно можно вывести - логически, если объект сам по себе, то он должен тестироваться как эквивалентный самому себе.
В большинстве случаев эта логика верна, но она зависит от реализации специального метода __eq__
. Как говорят документы,
Поведение по умолчанию для сравнения равенства (==
и !=
) Основано на идентичности объектов. Следовательно, сравнение сравнений экземпляров с одной и той же идентичностью приводит к равенству, а сравнение сравнений экземпляров с разными идентичностями приводит к неравенству. Мотивацией для этого поведения по умолчанию является желание, чтобы все объекты были рефлексивными (т.е. X есть y, означает x == y).
и в интересах согласованности рекомендует:
Сравнение равенства должно быть рефлексивным. Другими словами, одинаковые объекты должны сравниваться равными:
x is y
означает, что x == y
Мы видим, что это поведение по умолчанию для настраиваемых объектов:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
Контрапоставитель также обычно верен - если что-то проверяет как не равное, вы обычно можете сделать вывод, что они не являются одним и тем же объектом.
Поскольку тесты для равенства можно настроить, этот вывод не всегда выполняется для всех типов.
Исключение
Заметным исключением является nan
- он всегда проверяется как не равный самому себе:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
Проверка подлинности может быть гораздо более быстрой проверкой, чем проверка равенства (что может потребовать рекурсивные проверки членов).
Но он не может быть заменен равенством, где вы можете найти более одного объекта как эквивалент.
Обратите внимание, что сравнение равенства списков и кортежей предполагает, что идентичность объектов одинакова (потому что это быстрая проверка). Это может создать противоречия, если логика несовместима - как и для nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
Предупреждающая история:
Вопрос пытается использовать is
для сравнения целых чисел. Вы не должны предполагать, что экземпляр целого числа - это тот же экземпляр, что и полученный другой ссылкой. Эта история объясняет, почему.
У комментатора был код, основанный на том факте, что малые целые числа (-5 до 256 включительно) являются одноточечными в Python, вместо проверки на равенство.
Вау, это может привести к некоторым коварным ошибкам. У меня был код, который проверял, есть ли a, b, который работал так, как я хотел, потому что a и b обычно являются небольшими числами. Ошибка произошла только сегодня, спустя шесть месяцев в производстве, потому что a и b были, наконец, достаточно большими, чтобы их не кэшировали. - gwg
Он работал в разработке. Возможно, он прошел несколько уловок.
И он работал на производстве - до тех пор, пока код не проверил бы на целое число, превышающее 256, после чего он не удался в процессе производства.
Это производственный сбой, который можно было поймать в обзоре кода или, возможно, с помощью проверки стиля.
Позвольте мне подчеркнуть: не использовать is
для сравнения целых чисел.
Ответ 5
Они совершенно разные. is
проверяет идентичность объекта, а ==
проверяет равенство (понятие, которое зависит от типов двух операндов).
Это только счастливое совпадение, что " is
", кажется, правильно работает с маленькими целыми числами (например, 5 == 4 + 1). Это потому, что CPython оптимизирует хранение целых чисел в диапазоне (-5 до 256), делая их одиночными. Это поведение полностью зависит от реализации и не гарантируется, что оно будет сохранено при всех видах незначительных преобразовательных операций.
Например, Python 3.5 также делает короткие строки одиночными, но их нарезка нарушает это поведение:
>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
Ответ 6
Что разница между is
и ==
?
==
и is
другое сравнение! Как уже говорили другие:
-
==
сравнивает значения объектов. -
is
сравнивают ссылки объектов.
В именах Python ссылаются на объекты, например, в этом случае value1
и value2
относятся к экземпляру int
хранящему значение 1000
:
value1 = 1000
value2 = value1
![enter image description here]()
Поскольку value2
относится к одному и тому же объекту is
и ==
даст True
:
>>> value1 == value2
True
>>> value1 is value2
True
В следующем примере имена value1
и value2
относятся к разным экземплярам int
, даже если они сохраняют одно и то же целое число:
>>> value1 = 1000
>>> value2 = 1000
![enter image description here]()
Поскольку одно и то же значение (целое число) хранится ==
будет True
, поэтому его часто называют "сравнение значений". Однако is
будет возвращать значение False
, потому что это разные объекты:
>>> value1 == value2
True
>>> value1 is value2
False
Когда использовать какой?
Как правило, is
гораздо быстрее в сравнении. То, что кэширование CPython (или, может быть, повторное использование - лучший термин), - некоторые объекты, такие как маленькие целые числа, некоторые строки и т.д. Но это следует рассматривать как детали реализации, которые могут (хотя и маловероятно) меняться в любой момент без предупреждения.
Вы должны использовать только is
, если вы:
В любом другом случае вы должны использовать ==
для проверки равенства.
Могу ли я настроить поведение?
Есть некоторый аспект к ==
который уже не упоминался в других ответах: это часть Pythons "Модель данных". Это означает, что его поведение можно настроить с __eq__
метода __eq__
. Например:
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)))
Это просто искусственный пример, иллюстрирующий, что метод действительно называется:
>>> MyClass(10) == MyClass(10)
__eq__ method called
True
Обратите внимание, что по умолчанию (если нет другой реализации __eq__
не может быть найден в классе или суперкласса) __eq__
использует is
:
class AClass(object):
def __init__(self, value):
self._value = value
>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a
Поэтому на самом деле важно реализовать __eq__
если вы хотите "больше", чем просто сравнение ссылок для пользовательских классов!
С другой стороны, вы не можете настроить is
чека. Он всегда будет сравнивать, если у вас есть такая же ссылка.
Будут ли эти сравнения всегда возвращать логическое значение?
Поскольку __eq__
можно повторно реализовать или переопределить, он не ограничивается возвратом True
или False
. Он может вернуть что угодно (но в большинстве случаев он должен возвращать логическое значение!).
Например, с массивами NumPy функция ==
вернет массив:
>>> import numpy as np
>>> np.arange(10) == 2
array([False, False, True, False, False, False, False, False, False, False], dtype=bool)
Но is
проверка всегда будет возвращать True
или False
!
1 Как отметил Аарон Холл в комментариях:
Как правило, вы не должны делать это, is True
или is False
проверяет, потому что обычно он использует эти "проверки" в контексте, который неявно преобразует условие в логическое (например, в выражении if
). Таким образом, is True
сравнение is True
и неявное булевское литье делает больше работы, чем просто выполнение булевых бросков - и вы ограничиваете себя булевыми (что не считается pythonic).
Как упоминается PEP8:
Не сравнивайте значения boolean с True
или False
с помощью ==
.
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
Ответ 7
https://docs.python.org/library/stdtypes.html#comparisons
is
тесты для идентичности ==
тесты для равенства
Каждое (маленькое) целочисленное значение отображается на одно значение, поэтому каждые 3 идентичны и равны. Это деталь реализации, а не часть спецификации языка, хотя
Ответ 8
Ваш ответ верный. Оператор is
сравнивает идентичность двух объектов. Оператор ==
сравнивает значения двух объектов.
Идентификатор объекта никогда не изменяется после его создания; вы можете думать об этом как о адресе объекта в памяти.
Вы можете управлять сравнительным поведением значений объектов, определяя метод __cmp__
или богатый метод сравнения, например __eq__
.
Ответ 9
Взгляните на вопрос о переполнении стека Оператор Python "is" неожиданно работает с целыми числами.
В основном это сводится к тому, что "is
" проверяет, являются ли они одним и тем же объектом, а не просто равными друг другу (цифры ниже 256 являются особым случаем).
Ответ 10
Оператор ==
сравнивает значения обоих операндов и проверок равенства значений. В то время is
оператор проверяет, ссылаются ли оба операнда на один и тот же объект или нет.
a = [1,2,3,4]
b = a
print(a == b) # true
print(a is b) # true
Но если мы это сделаем
b = a[:] # b now references a copy of a
print(a == b) # true
print(a is b) # false
print(a is not b) # true
В принципе, is
можно считать сокращением для id(a) == id(b)
. Однако, помимо этого, есть причуды среды выполнения, которые еще больше усложняют ситуацию. Короткие строки и маленькие целые числа возвращают True
по сравнению с is
, из-за того, что машина Python пытается использовать меньше памяти для идентичных объектов.
a = 'python'
b = 'python'
print(a == b) # true
print(a is b) # true
Ответ 11
Как сказал Джон Фэминелла, большую часть времени вы будете использовать == и! =, потому что ваша цель - сравнивать значения. Я просто хотел бы классифицировать то, что вы делаете остальное время:
Существует один и только один экземпляр NoneType, т.е. None является одиночным. Следовательно, foo == None
и foo is None
означают одно и то же. Однако тест is
выполняется быстрее, и соглашение Pythonic должно использовать foo is None
.
Если вы делаете некоторые интроспекции или обманываете себя сбором мусора или проверяете, работает ли ваш настраиваемый гаджет для встроенных строк, или, например, вы используете прецедент для foo
is bar
.
Истинные и False также являются (сейчас) одиночными, но для foo == True
нет прецедента и нет использования для foo is True
.
Ответ 12
Большинство из них уже ответили на этот вопрос. Так же, как дополнительная заметка (основанная на моем понимании и экспериментировании, но не в документальном источнике), утверждение
== если объекты, на которые ссылаются переменные, равны
из вышеперечисленных ответов следует читать как
== если объекты, на которые ссылаются переменные, равны, а объекты, принадлежащие к одному типу/классу
Я пришел к такому выводу, основанному на следующем тесте:
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)
Здесь содержимое списка и кортежа одинаковы, но тип/класс разные.
Ответ 13
В двух словах, is
проверяет, является ли точка две ссылки на тот же объект или нет. ==
проверяет, имеют ли два объекта одинаковое значение или нет.
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
Ответ 14
На самом деле я хотел добавить это в качестве комментария, но не мог легко его украсить, поэтому, добавив в качестве ответа, пожалуйста, не считайте это ответом.
Вот что я понял -
выполните одно за другим и поймите вывод на каждом шаге
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
Ответ 15
Поскольку другие люди в этом сообщении подробно ответят на вопрос, я бы выделил в основном сравнение между is
и ==
для строк, которые могут дать разные результаты, и я настоятельно призывал программистов тщательно их использовать.
Для сравнения строк, убедитесь, что использовать ==
вместо is
:
str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')
Вне:
str is hello
str == hello
Но в приведенном ниже примере ==
и is
будет получить разные результаты:
str = 'hello sam'
if (str is 'hello sam'):
print ('str is hello sam')
if (str == 'hello sam'):
print ('str == hello sam')
Вне:
str == hello sam
Вывод:
Используйте is
осторожно, чтобы сравнить между строками
Ответ 16
Разница Python между is и equals (==)
Оператор может выглядеть так же, как оператор равенства, но они не одинаковы.
Проверяет, указывают ли обе переменные на один и тот же объект, тогда как знак == проверяет, совпадают ли значения для двух переменных.
Поэтому, если оператор is возвращает True, то равенство определенно верно, но противоположное может быть или не быть истинным.
Вот пример, демонстрирующий сходство и разницу.
>>> 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.
Ответ 17
Если вы сравниваете его с JavaScript (однако не рекомендуется сравнивать один язык с другим):
- Используйте
is
для строгого сравнения. Эквивалент Javascript (===
) - Используйте
==
для сравнения равенства.
Ответ 18
"==" сравнивает значения
"is" сравнивает базовые объекты
# this pgm is to show you the diff b/n == and is
# a==b and a is b
# == compares values
# is compares references i.e compares wether two variables refer to same object(memory)
a=10
b=10
print(a==b) # returns True as a,b have same value 10
print(a is b)
# returns True,
# we usually falsey assume that a =10 a new object . b=10 a new obj created
# but actually when b=10 ,nothing but b is pointed to 10 until value of a or b is changed from 10
a=[1]
b=[1]
print(a==b)
#returns True as a,b have a list element 1
print(a is b)
#returns False because here two different objs are created when initiated with lists
Ответ 19
o1 is o2 = > сравнивает, если o1 и o2 оба указывают на то же физическое местоположение в памяти (другими словами, если они являются одним и тем же объектом)
o1 == o2 = > здесь python вызывает метод o1 __cmp __ (o2), который идеально должен сравнивать значение и возвращать True или False. (Другими словами, он сравнивает значение)
Для людей JAVA:
-
В Java, чтобы определить, ссылаются ли две строковые переменные на одну и ту же
физической памяти, используя str1 == str2. (называемый объект
идентичность, и она написана в Python, поскольку str1 - str2).
-
Чтобы сравнить строковые значения в Java, usestr1.equals(str2); в Python,
используйте str1 == str2.
Пример:
class A():
...: def __init__(self,a):
...: self.a = a
...: def __repr__(self):
...: return str(self.a)
...: def __cmp__(self, value):
...: print self.a
...: print value.a
...: return cmp(self.a, value.a)
Выход оболочки Python:
o = A (2) o1 = o
o == o1 2 2 True
o - o1 True
o1 = A (2)
o - o1 False
Ответ 20
Хотя все эти ответы, которые полагаются на реализацию сравнения указателей возражений против сравнения значений, скорее всего, правильны, существует более глубокая синтаксическая причина использования is
для определения того, является ли значение переменной None
(в логической логике часто представлены как NULL
).
В реляционной базе данных и других логических системах NULL
подразумевает, что фактическое значение "неизвестно". Таким образом, логическое выражение xx == NULL
должно всегда оцениваться как NULL
, поскольку невозможно узнать, имеет ли значение xx
любое значение, которое оно может иметь, такое же, как и неизвестное значение. В языках программирования, которые более строго придерживаются правил логической логики, xx == NULL
(или Pythonically xx == None
) правильно оценивает значение NULL
, и для определения того, является ли значение переменной NULL
, должны быть предоставлены альтернативные средства. В этом отношении Python является выбросом из-за унитарного характера ссылки на объект None
. Но для ясности и логической корректности использование оператора сравнения Python is
кажется мне гораздо более обоснованной практикой.
Ответ 21
Да, между ними есть разница.
- '==': сравнивает объект по значению.
-
'in': сравнивает объект по ссылке.
a = [1,2,3]
b = a # both pointing to same object (memory location)
a == b:
True
a in b:
True #because a and b are pointing to same object
Теперь рассмотрим этот случай:
a = [1,2,3]
b = list(a) # creating copy of object a
a == b:
True # as values are same
a in b:
False # because they are pointing to different object.