Сравнение с использованием `==` сравнивает тождества перед сравнением значений?

Если я сравниваю две переменные, используя ==, сравнивает ли 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,

Другие вопросы по тегам