Сравнение с использованием `==` сравнивает тождества перед сравнением значений?
Если я сравниваю две переменные, используя ==
, сравнивает ли Python тождества, и, если они не совпадают, сравнивают значения?
Например, у меня есть две строки, которые указывают на один и тот же строковый объект:
>>> a = 'a sequence of chars'
>>> b = a
Это сравнивает значения или только идентификаторы?:
>>> b == a
True
Было бы целесообразно сначала сравнить личность, и я полагаю, что это так, но я еще не нашел ничего в документации, чтобы поддержать это. Самое близкое, что у меня есть, это:
x==y
звонкиx.__eq__(y)
который не говорит мне, сделано ли что-нибудь перед звонком x.__eq__(y)
,
2 ответа
Для пользовательских экземпляров классов is
используется как запасной вариант - где по умолчанию __eq__
не отменяется, a == b
оценивается как a is b
, Это гарантирует, что сравнение всегда будет иметь результат (за исключением NotImplemented
случай, когда сравнение явно запрещено).
Это (несколько косвенно - хорошее место, Sven Marnach) упоминается в документации модели данных (выделено мое):
Пользовательские классы имеют
__eq__()
а также__hash__()
методы по умолчанию; с ними все объекты сравниваются неравно (кроме самих себя) иx.__hash__()
возвращает соответствующее значение, так чтоx == y
подразумевает, чтоx is y
а такжеhash(x) == hash(y)
,
Вы можете продемонстрировать это следующим образом:
>>> class Unequal(object):
def __eq__(self, other):
return False
>>> ue = Unequal()
>>> ue is ue
True
>>> ue == ue
False
так __eq__
должен быть вызван до id
, но:
>>> class NoEqual(object):
pass
>>> ne = NoEqual()
>>> ne is ne
True
>>> ne == ne
True
так id
должен быть вызван где __eq__
не определено
Вы можете увидеть это в реализации CPython, которая отмечает:
/* If neither object implements it, provide a sensible default
for == and !=, but raise an exception for ordering. */
Реализация "разумного значения по умолчанию" представляет собой сравнение указателей на уровне C v
а также w
, который будет возвращать, указывают ли они на один и тот же объект.
В дополнение к ответу @jonrsharpe: если сравниваемые объекты реализуют __eq__
было бы неправильно для Python проверять идентичность в первую очередь.
Посмотрите на следующий пример:
>>> x = float('nan')
>>> x is x
True
>>> x == x
False
NaN - это особая вещь, которая никогда не должна сравниваться с собой; однако даже в этом случае x is x
должен вернуться True
из-за семантики is
,