Магические методы сравнения и декоратор @total_ordering
less_40__magic_methods/theory_01__comparison_methods.md
Таблица шести магических методов сравнения (__lt__, __le__, __gt__, __ge__, __eq__, __ne__) и декоратор functools.total_ordering, который достраивает недостающие методы, если реализованы только __eq__ и один из порядковых методов. Основная часть посвящена NotImplemented — специальному значению (не исключению), которое сигнализирует «я не умею сравнивать себя с этим типом» и заставляет Python попробовать обратный метод у другого операнда; если оба объекта возвращают NotImplemented — TypeError. Финальный пример показывает Person и Employee, изначально не умеющие сравниваться друг с другом, где через return NotImplemented Python сам переключается на other.__lt__(self), позволяя реализовать сравнение только в одном из двух классов.
- Таблица: <, <=, >, >=, ==, != → __lt__/__le__/__gt__/__ge__/__eq__/__ne__
- @total_ordering: реализовать __eq__ + один из порядковых — остальные достроятся
- NotImplemented — не исключение, сигнал попробовать обратный метод
- return NotImplemented вместо raise TypeError — не ломает возможность other.__gt__(self)
- Пример Person/Employee: p > e работает через p.__gt__(e) → NotImplemented → e.__lt__(p)
Показать начало файла (146 строк всего)
### Методы сравнения в Python
Чтобы объекты пользовательского класса можно было сравнивать, нужно определить специальные методы:
| Оператор | Спецметод | Значение |
| -------- | --------------------- | ---------------- |
| `<` | `__lt__(self, other)` | меньше |
| `<=` | `__le__(self, other)` | меньше или равно |
| `>` | `__gt__(self, other)` | больше |
| `>=` | `__ge__(self, other)` | больше или равно |
| `==` | `__eq__(self, other)` | равно |
| `!=` | `__ne__(self, other)` | не равно |
---
### Декоратор `@functools.total_ordering`
* Если добавить в класс декоратор `@functools.total_ordering`
* то достаточно реализовать один метод `__eq__`
* и один любой метод сравнения (`__lt__`, `__le__`, `__gt__`, `__ge__`).
Остальные 4 метода "добавит" сам декоратор.
---
#### Пример
```python
from functools import total_ordering
@total_ordering
class Person:
def __init__(self, age):
self.age = age
def __eq__(self, other):
return self.age == other.age
def __lt__(self, other):
return self.age < other.age
p1 = Person(30)
p2 = Person(25)
print(p1 > p2) # True
print(p1 <= p2) # False
print(p1 == p2) # False
```
Мы реализовали только:
* `__eq__`
* `__lt__`
Остальные (`>`, `>=`, `<=`) создал `total_ordering`.
---
### Исключение `NotImplemented`
…