Есть ли разница между "= = " и " is " в Python?
мой Google-fu не удалось мне.
в Python следующие два теста для равенства эквивалентны?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
справедливо ли это для объектов, где вы сравниваете экземпляры (a 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[:]
>>> 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
" Кажется, правильно работает с малыми целыми числами (например, 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
есть ли разница между
==
иis
в Python?
Да, у них есть очень важное отличие.
==
: проверьте равенство-семантика заключается в том, что эквивалентные объекты (которые не обязательно являются одним и тем же объектом) будут тестироваться как равные. Как информация:
операторы , ==, >=,
is
: проверьте идентичность-семантика заключается в том, что объект (как хранится в памяти) is объект. Опять же,информация:
операторы
is
и когда вы действительно имеете в видуif x is not None
-- например, при тестировании переменной или аргумента по умолчаниюNone
было установлено какое-то другое значение. Другое значение может иметь тип (например как контейнер), который может быть false в логическом контексте!
вывод равенства из личности
если в большинстве случаев это логика верно, но он полагается на реализацию поведение по умолчанию для сравнения равенства ( и в интересах последовательности, рекомендует: сравнение равенства должно быть рефлексивным. Другими словами, идентичные
объекты должны сравниваться равными: мы видим, что это поведение по умолчанию для пользовательских объектов: контрапозитивное также обычно верно-если что-то тест как не равный, вы обычно можете сделать вывод, что они не являются одним и тем же объектом. поскольку тесты на равенство могут быть настроены, этот вывод не всегда справедлив для всех типов. исключение: проверка идентичности может быть намного быстрее, чем проверка равенства (что может потребовать рекурсивной проверки членов). но его нельзя заменить равенством, где вы можете найти более одного объекта в качестве эквивалента. обратите внимание, что сравнение равенства списков и кортежей будет предполагать, что идентичность объектов равна (потому что это быстрая проверка). Это может создать противоречия, если логика непоследовательна - как это для вопрос пытается использовать у комментатора был код, который полагался на то, что малые целые числа (от -5 до 256 включительно) являются синглетами в Python, вместо проверки на равенство. Вау, это может привести к некоторым коварные жуки. У меня был код, который проверял, является ли a b, который работал так, как я хотел, потому что a и b обычно небольшие числа. Ошибка только произошла сегодня, после шести месяцев в производстве, потому что a и b, наконец, были достаточно большими, чтобы не кэшироваться. – gwg он работал в развитии. Возможно, он прошел какие-то испытания. и он работал в производстве-до тех пор, пока код не проверил целое число больше 256, и в этот момент он потерпел неудачу в производстве. это производственный сбой, который мог быть пойман в обзоре кода или, возможно, с помощью проверки стиля. позвольте мне подчеркните:не используйте is
верно, равенство может обычно
__eq__
специальный метод. Как docs сказать,
==
и !=
) основан на
идентичность объектов. Следовательно, равенство сравнение экземпляров
с такой же идентичностью приводит к равенству, и сравнение равенства
экземпляры с разными идентичностями приводят к неравенству. Ля
мотивацией для такого поведения по умолчанию является желание, чтобы все объекты
должно быть рефлексивным (т. е. 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
для сравнения чисел. Вы не должны предположим, что экземпляр целого числа является тем же экземпляром, что и экземпляр, полученный другой ссылкой. Эта история объясняет, почему.
is
для сравнения чисел.
https://docs.python.org/library/stdtypes.html#comparisons
is
тесты на личность
==
тесты на равенство
каждое (малое) целое значение сопоставляется с одним значением, поэтому каждые 3 идентичны и равны. Это деталь реализации, а не часть спецификации языка, хотя
в чем разница между 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 модуль)
на каждый другой случай, который вы должны использовать ==
для проверки равенства.
могу ли я настроить поведение?
есть некоторые аспекты, чтобы ==
это не было упомянуто уже в других ответах: это часть Pythons "модель данных". Это означает, что его поведение можно настроить с помощью __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__
может быть повторно реализован или переопределен, он не ограничивается return True
или False
. Это мог бы return anything (но в большинстве случаев он должен возвращать логическое значение!).
например, с массивами 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
сравнение и неявное логическое приведение выполняет больше работы, чем просто выполнение логического приведения - и вы ограничиваете себя в логических значений (который не является для Python).
как PEP8 упоминает:
не сравнивайте логические значения с
True
илиFalse
используя==
.Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
ваш ответ правильный. The is
оператор сравнивает идентичность двух объектов. The ==
оператор сравнивает значения двух объектов.
идентичность объекта никогда не изменяется после его создания; вы можете думать о нем как об адресе объекта в памяти.
вы можете контролировать поведение сравнения значений объектов, определяя __cmp__
способ или богатые сравнения методом __eq__
.
посмотрите на вопрос переполнения стека оператор "is" Python неожиданно ведет себя с целыми числами.
что он в основном сводится к тому, что "is
" проверяет, являются ли они одним и тем же объектом, а не просто равными друг другу (числа ниже 256 являются частным случаем).
как сказал Джон Феминелла, большую часть времени вы будете использовать == и != потому что ваша цель-сравнить ценности. Я просто хотел бы классифицировать то, что вы будете делать в остальное время:
существует один и только один экземпляр NoneType, т. е. None является синглтоном. Следовательно foo == None
и foo is None
означает то же самое. Однако is
тест быстрее, и Pythonic convention должен использовать foo is None
.
если вы делаете какой-то самоанализ или возиться с мусором сбор или проверка того, работает ли ваш встроенный гаджет для интернирования строк или что-то в этом роде, тогда у вас, вероятно, есть прецедент для foo
is bar
.
True и False также (теперь) синглеты, но нет прецедента для foo == True
и нет прецедента для foo is True
.
на самом деле я хотел добавить это в качестве комментария, но не мог украсить его легко, поэтому добавив в качестве ответа, пожалуйста, не рассматривайте это как ответ.
выполнить следующие один за другим и понять вывод на каждом шаге
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
большинство из них уже ответили на этот вопрос. Как дополнительная заметка (основанная на моем понимании и экспериментировании, но не из документированного источника), утверждение
== если объекты, на которые ссылаются переменные, равны
сверху ответы следует читать как
== если объекты, на которые ссылаются переменные, равны и объекты, принадлежащие к одному типу / классу
. Я прибыл в этот вывод основан на приведенном ниже тесте:
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
на ==
оператор сравнивает значения обоих операндов и проверяет равенство значений. Тогда как 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 и equals (==)
оператор is может показаться таким же, как оператор равенства, но это не одно и то же.
is проверяет, указывают ли обе переменные на один и тот же объект, тогда как знак == проверяет, совпадают ли значения двух переменных.
поэтому, если оператор 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.
"==" сравнивает значения
" 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 указывают на одно и то же физическое местоположение в памяти (другими словами, если они являются одним и тем же объектом)
О1 == О2 => здесь python вызывает метод o1 __cmp __(o2), который в идеале должен сравнивать значение и возвращать True или False. (Другими словами, он сравнивает значение)
для JAVA людей:
в Java, чтобы определить, являются ли две строковые переменные ссылка та же расположение физической памяти с помощью str1 выглядит следующим образом == стр2. (вызывается объект идентичность, и она написана в Python как str1 является str2).
Для сравнения строковых значений в Java, usestr1.равна(стр2); in Python, использовать str1 выглядит следующим образом == стр2.
пример:
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) О1 = o
о = о= О1 Два Два Правда
о О1 Правда
o1 = A (2)
о О1 Ложные
как и другие люди в этом посте ответить на вопрос в деталях, я бы подчеркнуть главным образом сравнение между is
и ==
для строк который может дать разные результаты, и я бы призвал программистов тщательно их использовать.
Для сравнения строк, обязательно используйте ==
вместо is
:
str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')
Out:
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')
Out:
str == hello sam
вывод:
использовать is
тщательно сравнить между строками
Да, есть разница между ними.
- '==': сравнивает объект по значению.
-
'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
должен всегда оценивать на , так как он невозможно когда-либо узнать, если xx
, какое бы значение он ни имел, это то же самое, что и неизвестное значение. В языках программирования, которые более строго придерживаются правил булевой логики,xx == NULL
(или Pythonically xx == None
) правильно оценивает в NULL
, и альтернативные средства должны быть предоставлены, чтобы определить, является ли значение переменной NULL
. Python является выбросом в этом отношении, из-за унитарного характера ссылки на объект None
. Но для ясности и логической корректности, используя Python is
оператор сравнения кажется мне гораздо более здравой практикой.