Есть ли разница между "= = " и " 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 в логическом контексте!

вывод равенства из личности

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

у комментатора был код, который полагался на то, что малые целые числа (от -5 до 256 включительно) являются синглетами в Python, вместо проверки на равенство.

Вау, это может привести к некоторым коварные жуки. У меня был код, который проверял, является ли a b, который работал так, как я хотел, потому что a и b обычно небольшие числа. Ошибка только произошла сегодня, после шести месяцев в производстве, потому что a и b, наконец, были достаточно большими, чтобы не кэшироваться. – gwg

он работал в развитии. Возможно, он прошел какие-то испытания.

и он работал в производстве-до тех пор, пока код не проверил целое число больше 256, и в этот момент он потерпел неудачу в производстве.

это производственный сбой, который мог быть пойман в обзоре кода или, возможно, с помощью проверки стиля.

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


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

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

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


в чем разница между 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
    • True1
    • False1
    • 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 оператор сравнения кажется мне гораздо более здравой практикой.