__eq__(self, other)
: Определяет равенство (==
).__ne__(self, other)
: Определяет неравенство (!=
).__lt__(self, other)
: Определяет "меньше чем" (<
).__gt__(self, other)
: Определяет "больше чем" (>
).__le__(self, other)
: Определяет "меньше или равно" (<=
).__ge__(self, other)
: Определяет "больше или равно" (>=
).__eq__
обычно требует переопределения __hash__
, чтобы обеспечить корректную работу с хеш-таблицами (например, в словарях и множествах).
Изменить поведение сравнения объектов по умолчанию в Python можно путем переопределения специальных (магических) методов класса, связанных с операторами сравнения. Вот основные методы:
__eq__(self, other)
: Определяет поведение оператора ==
(равно). Возвращает True
если объекты равны, иначе False
.__ne__(self, other)
: Определяет поведение оператора !=
(не равно). Возвращает True
если объекты не равны, иначе False
. По умолчанию возвращает результат, противоположный __eq__
.__lt__(self, other)
: Определяет поведение оператора <
(меньше). Возвращает True
если self
меньше other
, иначе False
.__le__(self, other)
: Определяет поведение оператора <=
(меньше или равно). Возвращает True
если self
меньше или равно other
, иначе False
.__gt__(self, other)
: Определяет поведение оператора >
(больше). Возвращает True
если self
больше other
, иначе False
.__ge__(self, other)
: Определяет поведение оператора >=
(больше или равно). Возвращает True
если self
больше или равно other
, иначе False
.Важные моменты:
__eq__
, __ne__
, __lt__
, __le__
, __gt__
, __ge__
) для обеспечения консистентного и предсказуемого поведения. Если реализован только один, остальные могут работать непредсказуемо.other
. Нужно предусмотреть обработку ситуаций, когда other
не является экземпляром класса self
. Часто полезно возвращать NotImplemented
, чтобы Python попробовал вызвать оператор с аргументами в обратном порядке (other.__eq__(self)
).__eq__
, то обязательно нужно переопределить __hash__
, чтобы объекты, которые считаются равными, имели одинаковые хэш-значения. Это важно для корректной работы со структурами данных, такими как словари и множества. Если __eq__
переопределен, а __hash__
нет, Python автоматически установит __hash__ = None
, что сделает объекты не хэшируемыми.functools.total_ordering
: Можно упростить реализацию методов сравнения с помощью декоратора functools.total_ordering
. Если реализованы __eq__
и еще один из методов сравнения (например, __lt__
), декоратор автоматически сгенерирует остальные методы. Это может сделать код более читаемым и менее подверженным ошибкам.Пример:
from functools import total_ordering
@total_ordering
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
if not isinstance(other, Point):
return NotImplemented
return self.x == other.x and self.y == other.y
def __lt__(self, other):
if not isinstance(other, Point):
return NotImplemented
return self.x < other.x or (self.x == other.x and self.y < other.y)
def __hash__(self):
return hash((self.x, self.y))
p1 = Point(1, 2)
p2 = Point(1, 2)
p3 = Point(2, 1)
print(p1 == p2) # True
print(p1 != p3) # True
print(p1 < p3) # True
print(p1 > p3) # False
print(p1 <= p2) # True
В этом примере класс Point
переопределяет __eq__
, __lt__
и __hash__
, а functools.total_ordering
генерирует остальные методы сравнения. Это позволяет сравнивать экземпляры класса Point
по их координатам.