Вопрос

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

Это было полезно?

Решение

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

Это работало в разработке.Возможно, он прошел некоторые модульные тесты.

И это работало в производстве — до тех пор, пока код не проверил целое число больше 256, после чего в производстве произошел сбой.

Это производственный сбой, который можно было обнаружить при проверке кода или, возможно, при проверке стиля.

Позвольте мне подчеркнуть: не использовать is для сравнения целых чисел.

В чем разница между 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:

    • None
    • True1
    • False1
    • 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#comparisons

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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]
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 

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

Вот что я сделал, чтобы понять...

выполните следующие действия один за другим и поймите вывод на каждом шаге

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

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

Оператор IS может показаться таким же, как оператор равенства, но они не одинаковы.

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

Поэтому, если оператор IS возвращает истину, то равенство определенно верно, но обратное может или не может быть правдой.

Вот пример, демонстрирующий сходство и различие.

>>> 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.

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

«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

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

о1 == о2 => здесь Python вызывает метод __cmp __(o2) o1, который в идеале должен сравнивать значение и возвращать True или False.(Другими словами, он сравнивает значение)

Для пользователей JAVA:

  • В Java, чтобы определить, ссылается ли две строковые переменные на одинаковое местоположение физической памяти, используя стр1 == стр2.(называется идентичностью объекта, и он написан в 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 is a1 true

о1 = А(2)

o is O1 ложный

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

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

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

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

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

  • '==' :сравнивает объект по значению.
  • 'в' :сравнивает объект по ссылке.

    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.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top