Есть ли разница между "==" и "есть"?

Мой 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, если вы:

  • хотите проверить, действительно ли два объекта являются одним и тем же объектом (а не только одно и то же "значение"). Один пример может быть, если вы используете одноэлементный объект как константу.
  • хотите сравнить значение с константой Python. Константы в Python:

    • None
    • True 1
    • False 1
    • NotImplemented
    • Ellipsis
    • __debug__
    • классы (например, int is int или int is float)
    • могут быть дополнительные константы во встроенных модулях или сторонних модулях. Например, np.ma.masked из модуля NumPy)

В любом другом случае вы должны использовать == для проверки равенства.

Могу ли я настроить поведение?

Есть некоторый аспект к == который уже не упоминался в других ответах: это часть 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__.

Ответ 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.