В комментарии к этому вопросу я увидел утверждение, в котором рекомендуется использовать
result is not None
против
result != None
Мне было интересно, в чем разница, и почему один может быть рекомендован по сравнению с другим?
В комментарии к этому вопросу я увидел утверждение, в котором рекомендуется использовать
result is not None
против
result != None
Мне было интересно, в чем разница, и почему один может быть рекомендован по сравнению с другим?
Ответы:
==
это тест на равенство . Он проверяет, являются ли правая сторона и левая сторона равными объектами (согласно их__eq__
или__cmp__
методам.)is
это испытание личности . Он проверяет, являются ли правая сторона и левая сторона одним и тем же объектом. Методы не выполняются, объекты не могут влиять наis
операцию.Вы используете
is
(иis not
) для одиночных игр, напримерNone
, когда вас не волнуют объекты, которые вы хотите притвориться,None
или где вы хотите защитить от разрушения объектов при сравнении с нимиNone
.источник
None
имеет мало методов и почти не имеет атрибутов. Если в вашем__eq__
тесте ожидался метод или атрибут, он может сломаться.def __eq__( self, other ): return self.size == other.size
, Например, сломается, еслиother
случитсяNone
.is
похож на Java==
. Питон==
похож на Java.equals()
. Конечно, это помогает, только если вы знаете Java.is
это похоже===
(очень равно), и наоборотis not
, похоже!==
(не совсем равно).is not
единственный оператор или это просто отрицание результатаis
как внутриnot foo is bar
?Во-первых, позвольте мне остановиться на нескольких терминах. Если вы просто хотите, чтобы на ваш вопрос ответили, прокрутите вниз до пункта «Ответ на ваш вопрос».
Определения
Идентификация объекта : когда вы создаете объект, вы можете назначить его переменной. Затем вы можете также назначить его другой переменной. И другой.
В этом случае
cancel
,close
иdismiss
все они относятся к одному объекту в памяти. Вы создали только одинButton
объект, и все три переменные ссылаются на этот один объект. Мы говорим, чтоcancel
,close
иdismiss
все ссылаются на идентичные объекты; то есть они относятся к одному объекту.Равенство объекта : Если сравнить два объекта, то , как правило , не волнует , что он относится к точному и тому же объекту в памяти. С помощью равенства объектов вы можете определить свои собственные правила сравнения двух объектов. Когда вы пишете
if a == b:
, вы, по сути, говоритеif a.__eq__(b):
. Это позволяет вам определить__eq__
метод,a
чтобы вы могли использовать свою собственную логику сравнения.Обоснование сравнений на равенство
Обоснование: два объекта имеют одинаковые данные, но не идентичны. (Это не один и тот же объект в памяти.) Пример: строки
Примечание: я использую строки Unicode здесь, потому что Python достаточно умен, чтобы повторно использовать обычные строки без создания новых в памяти.
Здесь у меня есть две строки Unicode,
a
иb
. У них одинаковое содержание, но они не являются одним и тем же объектом в памяти. Однако, когда мы сравниваем их, мы хотим, чтобы они сравнивались на равных. Здесь происходит то, что объект Unicode реализовал__eq__
метод.Примечание:
__eq__
онunicode
определенно реализован более эффективно, чем этот.Обоснование: два объекта имеют разные данные, но считаются одним и тем же объектом, если некоторые ключевые данные совпадают. Пример: большинство типов данных модели
Здесь у меня есть два монитора Dell,
a
иb
. Они имеют одинаковую марку и модель. Однако они не имеют одинаковых данных и не являются одним и тем же объектом в памяти. Однако, когда мы сравниваем их, мы хотим, чтобы они сравнивались на равных. Здесь происходит то, что объект Monitor реализует__eq__
метод.Отвечая на ваш вопрос
При сравнении
None
всегда используйтеis not
. Ни один из них не является синглтоном в Python - в памяти есть только один его экземпляр.Сравнивая идентичность , это можно сделать очень быстро. Python проверяет, имеет ли объект, на который вы ссылаетесь, тот же адрес памяти, что и глобальный объект None, - очень и очень быстрое сравнение двух чисел.
Сравнивая равенство , Python должен выяснить, есть ли у вашего объекта
__eq__
метод. Если это не так, он проверяет каждый суперкласс в поисках__eq__
метода. Если он находит, Python вызывает его. Это особенно плохо, если__eq__
метод медленный и не сразу возвращается, когда замечает, что другой объектNone
.Вы не реализовали
__eq__
? Тогда Python, вероятно, найдет__eq__
методobject
и использует его вместо этого - который все равно проверяет идентичность объекта.При сравнении большинства других вещей в Python вы будете использовать
!=
.источник
Учтите следующее:
источник
None
является одноэлементным, поэтому сравнение идентичности всегда будет работать, тогда как объект может подделать сравнение на равенство через.__eq__()
.источник
None
, но неправильное поведение в отношенииNone
могло бы возникнуть как побочный эффект от реализации равенства против других типов. Это не столько последствия для безопасности, сколько просто последствия для правильности.Некоторые объекты являются синглетонами и, следовательно,
is
с ними эквивалентны==
. Большинство нет.источник
()
и1
не являются по своей сути одиночками.-NSMALLNEGINTS <= n <= NSMALLPOSINTS
) и пустые кортежи являются синглетонами. На самом деле это не задокументировано и не гарантировано, но вряд ли изменится.