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
1False
1NotImplemented
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" неожиданно ведет себя с целыми числами.
То, что это в основном сводится к тому, что "is
msgstr "проверяет, являются ли они одним и тем же объектом, а не просто равным друг другу (числа ниже 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
Оператор сравнения мне кажется гораздо более здравой практикой.