В комментарии этот вопрос я увидел выражение, в котором рекомендуется использовать
result is not None
против
result != None
Мне было интересно, какая разница, и почему можно было бы рекомендовать другую?
В комментарии этот вопрос я увидел выражение, в котором рекомендуется использовать
result is not None
против
result != None
Мне было интересно, какая разница, и почему можно было бы рекомендовать другую?
==
- это тест равенства. Он проверяет, являются ли правая сторона и левая сторона равными объектами (в соответствии с их методами __eq__
или __cmp__
.)
is
является тестом идентификации. Он проверяет, является ли правая сторона и левая сторона одним и тем же объектом. Никаких методов не выполняется, объекты не могут влиять на операцию is
.
Вы используете is
(и is not
) для синглонов, например None
, где вам не нужны объекты, которые могут претендовать на None
, или где вы хотите защитить от разрушения объектов, когда сравнивается с None
.
Во-первых, позвольте мне пересмотреть несколько терминов. Если вы просто хотите, чтобы ваш вопрос ответил, прокрутите вниз до "Ответ на ваш вопрос".
Идентификатор объекта. Когда вы создаете объект, его можно присвоить переменной. Затем вы можете назначить другую переменную. И еще.
>>> 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 a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
Примечание. Я использую строки Юникода здесь, потому что 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__
on 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__()
.
>>> () is () True >>> 1 is 1 True >>> (1,) == (1,) True >>> (1,) is (1,) False >>> a = (1,) >>> b = a >>> a is b True
Некоторые объекты являются одноточечными, и, следовательно, is
с ними эквивалентно ==
. Большинство нет.
просто хочу знать, правильно ли я понимаю
так это б вполне буквально тестирование, если "а" это то же самое, как "Ъ"
и a == b просто проверяет, является ли 'a' РАВНЫМ 'b'