В комментарии к этому вопросу я увидел утверждение, в котором рекомендуется использовать
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
?
Во-первых, позвольте мне остановиться на нескольких терминах. Если вы просто хотите, чтобы на ваш вопрос ответили, прокрутите вниз до пункта «Ответ на ваш вопрос».
Идентификация объекта : когда вы создаете объект, вы можете назначить его переменной. Затем вы можете также назначить его другой переменной. И другой.
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
В этом случае cancel
, close
и dismiss
все они относятся к одному объекту в памяти. Вы создали только один Button
объект, и все три переменные ссылаются на этот один объект. Мы говорим, что cancel
, close
и dismiss
все ссылаются на идентичные объекты; то есть они относятся к одному объекту.
Равенство объекта : Если сравнить два объекта, то , как правило , не волнует , что он относится к точному и тому же объекту в памяти. С помощью равенства объектов вы можете определить свои собственные правила сравнения двух объектов. Когда вы пишете if a == b:
, вы, по сути, говорите if a.__eq__(b):
. Это позволяет вам определить __eq__
метод, a
чтобы вы могли использовать свою собственную логику сравнения.
Обоснование: два объекта имеют одинаковые данные, но не идентичны. (Это не один и тот же объект в памяти.) Пример: строки
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
Примечание: я использую строки Unicode здесь, потому что Python достаточно умен, чтобы повторно использовать обычные строки без создания новых в памяти.
Здесь у меня есть две строки Unicode, a
и b
. У них одинаковое содержание, но они не являются одним и тем же объектом в памяти. Однако, когда мы сравниваем их, мы хотим, чтобы они сравнивались на равных. Здесь происходит то, что объект Unicode реализовал __eq__
метод.
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
Примечание: __eq__
он unicode
определенно реализован более эффективно, чем этот.
Обоснование: два объекта имеют разные данные, но считаются одним и тем же объектом, если некоторые ключевые данные совпадают. Пример: большинство типов данных модели
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
Здесь у меня есть два монитора Dell, a
и b
. Они имеют одинаковую марку и модель. Однако они не имеют одинаковых данных и не являются одним и тем же объектом в памяти. Однако, когда мы сравниваем их, мы хотим, чтобы они сравнивались на равных. Здесь происходит то, что объект Monitor реализует __eq__
метод.
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
При сравнении None
всегда используйте is not
. Ни один из них не является синглтоном в Python - в памяти есть только один его экземпляр.
Сравнивая идентичность , это можно сделать очень быстро. Python проверяет, имеет ли объект, на который вы ссылаетесь, тот же адрес памяти, что и глобальный объект None, - очень и очень быстрое сравнение двух чисел.
Сравнивая равенство , Python должен выяснить, есть ли у вашего объекта __eq__
метод. Если это не так, он проверяет каждый суперкласс в поисках __eq__
метода. Если он находит, Python вызывает его. Это особенно плохо, если __eq__
метод медленный и не сразу возвращается, когда замечает, что другой объект None
.
Вы не реализовали __eq__
? Тогда Python, вероятно, найдет __eq__
метод object
и использует его вместо этого - который все равно проверяет идентичность объекта.
При сравнении большинства других вещей в Python вы будете использовать !=
.
Учтите следующее:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
None
является одноэлементным, поэтому сравнение идентичности всегда будет работать, тогда как объект может подделать сравнение на равенство через .__eq__()
.
None
, но неправильное поведение в отношении None
могло бы возникнуть как побочный эффект от реализации равенства против других типов. Это не столько последствия для безопасности, сколько просто последствия для правильности.
>>> () есть () Правда >>> 1 есть 1 Правда >>> (1,) == (1,) Правда >>> (1,) есть (1,) Ложь >>> a = (1,) >>> б = а >>> а б Правда
Некоторые объекты являются синглетонами и, следовательно, is
с ними эквивалентны ==
. Большинство нет.
()
и 1
не являются по своей сути одиночками.
-NSMALLNEGINTS <= n <= NSMALLPOSINTS
) и пустые кортежи являются синглетонами. На самом деле это не задокументировано и не гарантировано, но вряд ли изменится.