Мой 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
тесты, чтобы увидеть, являются ли они одним и тем же объектом?
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
выход:False True False
.b = a[:]
частью копирования списка операторов слайсов, поэтому я отредактировал ваш ответ, чтобы оставить там комментарий. Похоже, я только что достиг порога, чтобы не нужно было пересматривать мои правки, прежде чем они будут применены, так что, надеюсь, это здорово с вами. Независимо от этого, вот полезный справочник о том, как копировать списки, на которые я натолкнулся и на которые мне пришлось ссылаться, чтобы выяснить, что вы делаете: stackoverflow.com/a/2612815/4561887==
. Так,5.0
например, значение с плавающей запятой, а5
целое число. Но5.0 == 5
все равно вернется,True
потому что они представляют одну и ту же ценность. С точки зрения производительности и утки,is
он всегда проверяется интерпретатором, сравнивая адреса памяти операнда, в то время==
как объект сам решает, определяет ли он себя как что-то еще.1000 is 10**3
оценивается как True в Python 3.7, поскольку 10 ** 3 является типомint
. Но1000 is 1e3
оценивается как False, поскольку 1e3 является типомfloat
.1000 is 10**3
true зависит от реализации и зависит от предварительной оценки выражения компилятором10**3
.x=10; 1000 is x**3
оценивает доFalse
.Существует простое правило, чтобы сказать вам, когда использовать
==
илиis
.==
для равенства ценностей . Используйте его, когда хотите узнать, имеют ли два объекта одинаковое значение.is
для справочного равенства . Используйте его, когда хотите узнать, ссылаются ли две ссылки на один и тот же объект.В общем, когда вы сравниваете что-то с простым типом, вы обычно проверяете равенство значений , поэтому вам следует использовать его
==
. Например, цель вашего примера, вероятно, состоит в том, чтобы проверить, имеет ли x значение, равное 2 (==
), а не указывает лиx
буквально на тот же объект, что и 2.Еще кое-что, на что следует обратить внимание: из-за того, как работает реализация ссылок CPython, вы получите неожиданные и противоречивые результаты, если по ошибке будете использовать
is
для сравнения ссылок на целые числа:Это в значительной степени то, что мы ожидали:
a
иb
имеют одинаковую ценность, но являются различными объектами. Но как насчет этого?Это не согласуется с более ранним результатом. Что тут происходит? Оказывается, эталонная реализация Python кэширует целочисленные объекты в диапазоне -5..256 как единичные экземпляры по соображениям производительности. Вот пример, демонстрирующий это:
Это еще одна очевидная причина не использовать
is
: поведение оставлено на усмотрение реализации, когда вы ошибочно используете его для равенства значений.источник
a=500
иb=500
, просто хотел бы отметить, что если вы установитеa
иb
интергер между [-5, 256], наa is b
самом деле возвращаетTrue
. Больше информации здесь: stackoverflow.com/q/306313/7571052==
определяет, равны ли значения, аis
определяет, являются ли они точно таким же объектом.источник
Да, у них есть очень важное различие.
==
: проверьте на равенство - семантика состоит в том, что эквивалентные объекты (которые не обязательно являются одним и тем же объектом) будут проверяться как равные. Как сказано в документации :is
: проверьте идентичность - семантика заключается в том, что объект (как хранится в памяти) является объектом. Опять же, в документации сказано :Таким образом, проверка на идентичность аналогична проверке на равенство идентификаторов объектов. Это,
такой же как:
где
id
- встроенная функция, которая возвращает целое число, которое «гарантированно будет уникальным среди одновременно существующих объектов» (см.help(id)
) и гдеa
иb
- любые произвольные объекты.Другие направления использования
Вы должны использовать эти сравнения для их семантики. Используйте,
is
чтобы проверить идентичность и==
проверить равенство.В общем, мы используем
is
для проверки личности. Это обычно полезно, когда мы проверяем объект, который должен существовать только один раз в памяти, называемый в документации «синглтоном».Варианты использования для
is
включают в себя:None
Обычные варианты использования
==
включают в себя:Общий случай использования, опять же , для
==
, это объект , который вы хотите , не может быть тот же объект, а это может быть эквивалентно одинPEP 8 направлений
PEP 8, официальное руководство по стилю Python для стандартной библиотеки, также упоминает два варианта использования для
is
:Вывод равенства из идентичности
Если
is
это правда, равенство обычно можно вывести - логически, если объект сам по себе, то он должен проверяться как эквивалентный самому себе.В большинстве случаев эта логика верна, но она опирается на реализацию
__eq__
специального метода. Как говорят документы ,и в интересах последовательности рекомендует:
Мы можем видеть, что это поведение по умолчанию для пользовательских объектов:
Противоположное также обычно верно - если что-то проверяется как не равное, вы можете сделать вывод, что это не один и тот же объект.
Поскольку тесты на равенство могут быть настроены, этот вывод не всегда верен для всех типов.
Исключение
Заметное исключение
nan
- оно всегда тестируется как не равное себе:Проверка на идентичность может быть намного быстрее, чем проверка на равенство (что может потребовать рекурсивной проверки членов).
Но его нельзя заменить равенством, когда вы можете найти более одного объекта в качестве эквивалента.
Обратите внимание, что сравнение равенства списков и кортежей предполагает, что идентичность объектов одинакова (потому что это быстрая проверка). Это может создать противоречия, если логика противоречива - как это для
nan
:Поучительная история:
Вопрос пытается использовать
is
для сравнения целых чисел. Не следует предполагать, что экземпляр целого числа совпадает с экземпляром, полученным по другой ссылке. Эта история объясняет почему.У комментатора был код, который основывался на том факте, что маленькие целые числа (от -5 до 256 включительно) в Python являются синглетонами вместо проверки на равенство.
Это работало в разработке. Возможно, прошло несколько юнит-тестов.
И он работал в производстве - до тех пор, пока код не проверил целое число больше 256, и в этот момент он не заработал.
Это производственный сбой, который мог быть обнаружен при проверке кода или, возможно, при проверке стиля.
Позвольте мне подчеркнуть: не используйте
is
для сравнения целых чисел.источник
is None
являющаяся исключением, но это== None
тоже работает ...is
для сравненияEnum
.Какая разница между
is
а==
?==
иis
разные сравнения! Как уже говорили другие:==
сравнивает значения объектов.is
сравнивает ссылки объектов.В Python имена ссылаются на объекты, например, в этом случае
value1
иvalue2
ссылаются наint
экземпляр, хранящий значение1000
:Потому что
value2
относится к тому же объектуis
и==
дастTrue
:В следующем примере имена
value1
иvalue2
ссылаются на разныеint
экземпляры, даже если оба хранят одно и то же целое число:Поскольку то же самое значение (целое число) хранятся
==
будетTrue
, поэтому его часто называют «сравнением значений». Однакоis
вернется,False
потому что это разные объекты:Когда использовать что?
Как правило
is
, это гораздо более быстрое сравнение. Вот почему CPython кэширует (или, возможно, повторное использование будет лучшим термином) определенные объекты, такие как маленькие целые числа, некоторые строки и т. Д. Но это следует рассматривать как детали реализации, которые могут (даже если вряд ли) измениться в любой момент без предупреждения.Вы должны использовать только
is
если вы:хочу сравнить значение с константой Python . Константы в Python:
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
илиint is float
)np.ma.masked
из модуля NumPy)В любом другом случае вы должны использовать
==
для проверки на равенство.Могу ли я настроить поведение?
Есть некоторый аспект
==
, который не был упомянут в других ответах: это часть Python, «Модель данных» . Это означает, что его поведение можно настроить с помощью__eq__
метода. Например:Это всего лишь искусственный пример, иллюстрирующий, что метод действительно называется:
Обратите внимание, что по умолчанию (если никакая другая реализация не
__eq__
может быть найдена в классе или суперклассах)__eq__
используетis
:Так что на самом деле важно реализовать,
__eq__
если вы хотите «больше», чем просто сравнение ссылок для пользовательских классов!С другой стороны, вы не можете настроить
is
чеки. Он всегда будет сравниваться, только если у вас одна и та же ссылка.Будут ли эти сравнения всегда возвращать логическое значение?
Поскольку
__eq__
может быть повторно реализован или переопределен, он не ограничивается возвратомTrue
илиFalse
. Он может вернуть все что угодно (но в большинстве случаев он должен возвращать логическое значение!).Например, для массивов NumPy
==
будет возвращен массив:Но
is
чеки всегда будут возвращатьсяTrue
илиFalse
!1 Как отметил Аарон Холл в комментариях:
Как правило, вы не должны делать никаких проверок
is True
илиis False
проверок, потому что обычно эти «проверки» используются в контексте, который неявно преобразует условие в логическое значение (например, вif
операторе). Таким образом,is True
сравнение и неявное логическое приведение делают больше работы, чем простое приведение - и вы ограничиваетесь булевыми значениями (которые не считаются питоническими).Как PEP8 упоминает:
источник
is
именами, которые указывают на логические значения, следует проверять с помощью логического контекста, напримерif __debug__:
илиif not __debug__:
. Вы никогда не должны делатьif __debug__ is True:
или,if __debug__ == True:
кроме того, константа - это просто постоянное семантическое значение, а не единичное, поэтому проверкаis
в этом случае не является семантически правильной. Я призываю вас найти источник в поддержку ваших утверждений - я не думаю, что вы найдете его.None
,True
,False
и__debug__
то , что вы могли бы назвать «постоянное семантическое значение», поскольку они не могут быть переназначены. Но все они синглтоны.is True
илиif False
проверка (но да, это довольно редко - но если вы сделаете их, вы можете сделать их, используяis
). Вот почему даже CPython использует их иногда (например, здесь или здесь )Они совершенно разные .
is
проверяет идентичность объекта, а==
проверяет равенство (понятие, которое зависит от типов двух операндов).Это только счастливое совпадение, что "
is
", кажется, работает правильно с маленькими целыми числами (например, 5 == 4 + 1). Это потому, что CPython оптимизирует хранение целых чисел в диапазоне (от -5 до 256), делая их одиночными . Это поведение полностью зависит от реализации и не гарантируется, что оно будет сохранено при всех видах незначительных преобразовательных операций.Например, Python 3.5 также делает короткие строки одиночными, но их нарезка нарушает это поведение:
источник
https://docs.python.org/library/stdtypes.html#comparisons
is
тесты на идентичность==
тесты на равенствоКаждое (маленькое) целочисленное значение отображается на одно значение, поэтому каждые 3 идентичны и равны. Это деталь реализации, а не часть языковой спецификации
источник
Ваш ответ правильный.
is
Оператор сравнивает идентичность двух объектов.==
Оператор сравнивает значения двух объектов.Идентичность объекта никогда не меняется после его создания; вы можете думать об этом как об адресе объекта в памяти.
Вы можете управлять поведением сравнения значений объекта, определяя
__cmp__
метод или расширенный метод сравнения, например__eq__
.источник
Взгляните на вопрос переполнения стека. Оператор Python «is» неожиданно ведет себя с целыми числами .
В основном это сводится к тому, что «
is
» проверяет, являются ли они одним и тем же объектом, а не просто равным друг другу (числа ниже 256 являются особым случаем).источник
В двух словах,
is
проверяет, указывают ли две ссылки на один и тот же объект или нет.==
проверяет, имеют ли два объекта одинаковое значение или нет.источник
Как сказал Джон Феминелла, большую часть времени вы будете использовать == и! =, Потому что ваша цель - сравнить значения. Я просто хотел бы классифицировать то, что вы будете делать в остальное время:
Существует один и только один экземпляр NoneType, т. Е. None является одиночным. Следовательно
foo == None
иfoo is None
значит то же самое. Тем не менее,is
тест быстрее и Pythonic соглашение использоватьfoo is None
.Если вы проводите некоторый самоанализ или разбираетесь со сборкой мусора или проверяете, работает ли ваш пользовательский встроенный гаджет для интернирования строк или что-то подобное, то у вас, вероятно, есть вариант использования для
foo
isbar
.Истина и Ложь также (в настоящее время) синглтоны, но нет ни одного варианта использования для,
foo == True
ни никакого варианта использования дляfoo is True
.источник
Большинство из них уже ответили на вопрос. Как дополнительная заметка (основываясь на моем понимании и экспериментах, но не на документированном источнике), заявление
Сверху ответы следует читать как
, Я пришел к такому выводу на основе теста ниже:
Здесь содержимое списка и кортежа одинаковы, но тип / класс различны.
источник
Разница в Python между is и equals (==)
Вот пример, демонстрирующий сходство и различие.
источник
Поскольку другие люди в этом посте подробно ответят на этот вопрос, я бы выделил в основном сравнение между
is
и==
для строк которые могут давать разные результаты, и я призываю программистов осторожно их использовать.Для сравнения строк обязательно используйте
==
вместоis
:Вне:
Но в приведенном ниже примере
==
иis
получим разные результаты:Вне:
Вывод:
Используйте
is
внимательно для сравнения между строкамиисточник