Is there a difference between "==" and "is"?

Мой 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 тесты, чтобы увидеть, если они один и тот же объект?

20 ответов

Решение

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

Пожалуйста, смотрите этот вопрос также.

Существует простое правило, чтобы сказать вам, когда использовать == или же 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: поведение оставлено на усмотрение реализации, когда вы ошибочно используете его для равенства значений.

Есть ли разница между == а также is в питоне?

Да, у них есть очень важное различие.

==: проверьте на равенство - семантика состоит в том, что эквивалентные объекты (которые не обязательно являются одним и тем же объектом) будут проверяться как равные. Как сказано в документации:

Операторы <,>, ==, >=, <= и!= Сравнивают значения двух объектов.

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

В большинстве случаев эта логика верна, но она опирается на реализацию __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 сравнить целые числа.

== определяет, равны ли значения, а is определяет, являются ли они точно таким же объектом и равными.

В чем разница между is а также ==?

== а также is разные сравнения! Как уже говорили другие:

  • == сравнивает значения объектов.
  • is сравнивает ссылки объектов.

В Python имена относятся к объектам, например, в этом случае value1 а также value2 обратиться к int экземпляр, хранящий значение 1000:

value1 = 1000
value2 = value1

Так как value2 относится к тому же объекту is а также == дам True:

>>> value1 == value2
True
>>> value1 is value2
True

В следующем примере имена value1 а также value2 относятся к разным int экземпляры, даже если оба хранят одно и то же целое число:

>>> value1 = 1000
>>> value2 = 1000

Поскольку одно и то же значение (целое число) сохраняется == будет 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)

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

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

Есть некоторый аспект == это не было упомянуто в других ответах: это часть Питона "Модель данных". Это означает, что его поведение можно настроить с помощью __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 Сравнение и неявное логическое приведение выполняет больше работы, чем просто приведение логического преобразования, и вы ограничиваетесь булевыми значениями (которые не считаются питоническими).

Как PEP8 упоминает:

Не сравнивайте логические значения с True или же False с помощью ==,

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

Они совершенно разные. 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

https://docs.python.org/library/stdtypes.html

is тесты на личность== тесты на равенство

Каждое (маленькое) целочисленное значение отображается на одно значение, поэтому каждые 3 идентичны и равны. Это деталь реализации, а не часть языковой спецификации

Ваш ответ правильный. is Оператор сравнивает идентичность двух объектов. == Оператор сравнивает значения двух объектов.

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

Вы можете контролировать поведение сравнения значений объекта, определяя __cmp__ метод или богатый метод сравнения, как __eq__,

Поскольку другие люди в этом посте подробно отвечают на этот вопрос, я бы выделил в основном сравнение между 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 тщательно сравнивать между строками

Обратите внимание на вопрос переполнения стека. Оператор Python "is" неожиданно ведет себя с целыми числами.

То, что это в основном сводится к тому, что "ismsgstr "проверяет, являются ли они одним и тем же объектом, а не просто равным друг другу (числа ниже 256 - особый случай).

В двух словах, 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 

Как сказал Джон Феминелла, большую часть времени вы будете использовать == и!=, Потому что ваша цель - сравнить значения. Я просто хотел бы классифицировать то, что вы будете делать в остальное время:

Существует один и только один экземпляр NoneType, т. Е. None не является синглтоном. как следствие foo == None а также foo is None значит то же самое. Тем не менее is тест быстрее, и соглашение Pythonic должно использовать foo is None,

Если вы занимаетесь самоанализом или копаете сборщик мусора или проверяете, работает ли ваш пользовательский встроенный гаджет для интернирования строк или что-то подобное, то у вас, вероятно, есть сценарий использования для foo является bar,

True и False также являются (сейчас) синглетонами, но для foo == True и нет варианта использования для foo is True,

Разница в Python между is и equals(==)

Оператор is может выглядеть так же, как оператор равенства, но они не совпадают.

Is проверяет, указывают ли обе переменные на один и тот же объект, а знак == проверяет, совпадают ли значения двух переменных.

Поэтому, если оператор is возвращает True, тогда равенство определенно True, но противоположное может быть или не быть 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.

Большинство из них уже ответили на вопрос. Как дополнительная заметка (основываясь на моем понимании и экспериментах, но не на документированном источнике), заявление

== если объекты, на которые ссылаются переменные, равны

Сверху ответы следует читать как

== если объекты, на которые ссылаются переменные, равны и объекты принадлежат к одному типу / классу

, Я пришел к такому выводу на основе теста ниже:

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)

Здесь содержимое списка и кортежа одинаковы, но тип / класс различны.

== Оператор сравнивает значения обоих операндов и проверяет равенство значений. В то время как 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

На самом деле я хотел добавить это как комментарий, но не мог украсить его легко, поэтому добавив в качестве ответа, пожалуйста, не рассматривайте это как ответ.

Это то, что я сделал, чтобы понять -

выполнять по очереди и понимать вывод на каждом шаге

a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b

Если вы сравниваете его с JavaScript (однако не рекомендуется сравнивать один язык с другим):

  • использование is для строгого сравнения. Эквивалент Javascript (===)
  • использование == для сравнения равенства.

"==" сравнивает значения

"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

o1 равно o2 => сравнивает, если o1 и o2 оба указывают на одно и то же физическое местоположение в памяти (другими словами, если они являются одним и тем же объектом)

o1 == o2 => здесь Python вызывает метод __cmp __(o2) o1, который в идеале должен сравнивать значение и возвращать 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 Shell:

o = A (2) o1 = o

o == o1 2 2 True

o is o1 True

o1 = A (2)

o is o1 False

Да, есть разница между обоими.

  • '==': сравнивает объект по значению.
  • '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.

Хотя все эти ответы, основанные на реализации сравнения указателей на возражения и сравнения значений, скорее всего верны, существует более глубокая синтаксическая причина использования is определить, является ли значение переменной None (в булевой логике часто представляется как NULL).

В реляционной базе данных и других логических системах, NULL подразумевает, что фактическое значение "неизвестно". Таким образом, логическое выражение xx == NULL всегда должен оценивать NULL само по себе, так как невозможно узнать, xxКакое бы значение оно не имело, оно равно неизвестному значению. В языках программирования, которые более строго придерживаются правил булевой логики, xx == NULL (или Pythonically xx == None) правильно оценивает NULLи должны быть предоставлены альтернативные средства, чтобы определить, является ли значение переменной NULL, В этом отношении Python выделяется из-за унитарного характера ссылки на объект None, Но для ясности и логической корректности, используя Python is Оператор сравнения мне кажется гораздо более здравой практикой.

Другие вопросы по тегам