Операторы сравнения vs "богатые методы сравнения" в Python
Может ли кто-нибудь объяснить мне разницу между ними? Те, как правило, эквивалентны ? Может быть, я здесь совершенно не прав, но я думал, что каждый оператор сравнения обязательно связан с одним "богатым методом сравнения". Это из документации:
Соответствие между символами операторов и именами методов выглядит следующим образом:
образом:
x<yзвонкиx.__lt__(y),x<=yзвонкиx.__le__(y),x==yзвонкиx.__eq__(y),x!=yзвонкиx.__ne__(y),x>yвызовыx.__gt__(y), иx>=yзвонкиx.__ge__(y).
Вот пример, который демонстрирует мое замешательство.
Питон 3.x:
dict1 = {1:1}
dict2 = {2:2}
>>> dict1 < dict2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'dict' and 'dict'
>>> dict1.__lt__(dict2)
NotImplemented
Питон 2.x:
dict1 = {1:1}
dict2 = {2:2}
>>> dict1 < dict2
True
>>> dict1.__lt__(dict2)
NotImplemented
Из примера python 3 кажется логичным, что вызов dict1 < dict2 не поддерживается. Но как насчет примера Python 2 ? Почему это принято ?
Я знаю, что в отличие от Python 2, в Python 3 не все объекты поддерживают операторы сравнения. К моему удивлению, однако, обе версии возвращают синглтон NotImplemented, когда вызов __lt__().
2 ответов:
Это зависит от волшебного метода
__cmp__, который должен был заменить операторы богатого сравнения:>>> dict1 = {1:1} >>> dict2 = {2:2} >>> dict1.__cmp__ <method-wrapper '__cmp__' of dict object at 0x10f075398> >>> dict1.__cmp__(dict2) -1Что касается упорядочивания логики , то вот документация Python 2.7 :
Отображения (экземпляры dict) сравниваются равными тогда и только тогда, когда они имеют равные (ключ, значение) пары. Равенство сравнение ключей и значений усиливает рефлексивность.
Результаты, отличные от равенства, разрешаются последовательно, но не являются иначе определено.
Со сноской:
Более ранние версии Python использовали лексикографическое сравнение отсортированных (ключ, значение) списки, но это было очень дорого для общего случая сравнение для равенства. Еще более ранняя версия Python по сравнению словари только по идентичности, но это вызвало удивление, потому что люди ожидали, что смогут проверить словарь на пустоту с помощью сравнивая его с {}.
И, в Python 3.0, упорядочивание была упрощена. Это из документации :
Операторы сравнения порядка
(<, <=, >=, >)вызывают ошибку типа исключение, когда операнды не имеют осмысленного естественного порядка.
builtin.sorted()иlist.sort()больше не принимает аргумент cmp предоставление функции сравнения. Вместо этого используйте ключевой аргумент.Функция
cmp()должна рассматриваться как Исчезнувшая, а специальный метод__cmp__()больше не поддерживается. Используйте__lt__()для сортировки,__eq__()с__hash__(), и другие богатые сравнения по мере необходимости. (Если вам действительно нужна функциональностьcmp(), Вы можете использовать выражение(a > b) - (a <> b)как эквивалент дляcmp(a, b).)Таким образом, чтобы быть явным, в Python 2, поскольку богатые операторы сравнения не реализованы, объекты
dictбудут откатываться к__cmp__, из документации модели данных :
object.__cmp__(self, other)
Вызывается операциями сравнения, если богат сравнение (см. выше) не определено. Должны вернуть отрицательный целое число, если самостоятельно другого.
Примечание для оператора
<по сравнению с__lt__:import types class A: def __lt__(self, other): return True def new_lt(self, other): return False a = A() print(a < a, a.__lt__(a)) # True True a.__lt__ = types.MethodType(new_lt, a) print(a < a, a.__lt__(a)) # True False A.__lt__ = types.MethodType(new_lt, A) print(a < a, a.__lt__(a)) # False False
<вызовы__lt__, определенные в классе;__lt__вызовы__lt__, определенные в объекте.Обычно это одно и то же:) и это совершенно восхитительно использовать:
A.__lt__ = new_lt
Comments