МУНИЦИПАЛЬНОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ДОПОЛНИТЕЛЬНОГО ОБРАЗОВАНИЯ
«ЦЕНТР ДЕТСКОГО ТЕХНИЧЕСКОГО ТВОРЧЕСТВА»
Методическая разработка
«Магические методы операций сравнения в языке Python»
к дополнительной общеобразовательной
общеразвивающей программе
технической направленности
«Программирование на Python»
Возраст детей: 10-17 лет
Автор: Костычев Вадим Александрович
г. Заречный Пензенской области
2025 г.
Данный материал предназначен для преподавателей информатики, программирования и студентов (учащихся), изучающих язык программирования Python. Он может быть использован как на лекциях, так и при проведении практических занятий или самостоятельной работе.
Цель: формирование у учащихся понимания механизма реализации операций сравнения для пользовательских объектов в языке Python посредством магических (специальных) методов, а также развитие навыков проектирования классов с логически корректным и семантически осмысленным поведением при сравнении.
Задачи:
Познакомить обучающихся с магическими методами, отвечающими за операции сравнения (__eq__, __ne__, __lt__, __le__, __gt__, __ge__).
Объяснить принципы реализации логики сравнения в пользовательских классах.
Продемонстрировать, как сделать объекты класса совместимыми с функциями и конструкциями, использующими сравнение (например, sorted(), max(), if, in).
Зачем нужны операции сравнения для пользовательских объектов?
Встроенные типы Python (например, int, str, list) поддерживают сравнение:
print(5 3) # → True
print("яблоко"
Однако при создании собственного класса сравнение по умолчанию не определено. Без реализации соответствующих магических методов любая попытка сравнения (кроме is) приведёт к поведению по умолчанию: сравнению по идентичности ссылок (аналог is). Это почти никогда не соответствует логике предметной области.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p1 = Point(1, 2)
p2 = Point(1, 2)
print(p1 == p2) # → False! Хотя координаты одинаковые.
Чтобы сравнение работало логично, необходимо явно определить магические методы.
Основные магические методы сравнения
| Оператор | Магический метод | Назначение |
| == | __eq__(self, other) | Проверка на равенство |
| != | __ne__(self, other) | Проверка на неравенство |
| | __lt__(self, other) | Меньше |
| | __le__(self, other) | Меньше или равно |
| | __gt__(self, other) | Больше |
| = | __ge__(self, other) | Больше или равно |
Начиная с Python 3.7+, если определён __eq__, но не определён __hash__, объект автоматически становится нехэшируемым (что нормально для изменяемых объектов).
Если вы реализуете упорядочение (например,
Практические примеры
Пример: Класс Point (точка на плоскости)
Сравнение точек по расстоянию от начала координат:
import math
from functools import total_ordering
@total_ordering
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance_from_origin(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
def __eq__(self, other):
if not isinstance(other, Point):
return NotImplemented
return self.distance_from_origin() == other.distance_from_origin()
def __lt__(self, other):
if not isinstance(other, Point):
return NotImplemented
return self.distance_from_origin()
def __str__(self):
return f"Point({self.x}, {self.y})"
p1 = Point(3, 4) # расстояние = 5
p2 = Point(0, 5) # расстояние = 5
p3 = Point(1, 1) # расстояние ≈ 1.41
print(p1 == p2) # → True
print(p3
print(sorted([p1, p2, p3])) # → [Point(1, 1), Point(3, 4), Point(0, 5)]
Благодаря @total_ordering, автоматически работают , =.
Пример: Класс Student (ученик)
Сравнение учеников по среднему баллу:
from functools import total_ordering
@total_ordering
class Student:
def __init__(self, name, average_grade):
self.name = name
self.average_grade = average_grade
def __eq__(self, other):
if not isinstance(other, Student):
return NotImplemented
return self.average_grade == other.average_grade
def __lt__(self, other):
if not isinstance(other, Student):
return NotImplemented
return self.average_grade
def __str__(self):
return f"{self.name} ({self.average_grade})"
s1 = Student("Анна", 4.5)
s2 = Student("Борис", 4.8)
s3 = Student("Вера", 4.5)
print(s1 == s3) # → True
print(s1
students = [s1, s2, s3]
print(sorted(students, reverse=True)) # → [Борис (4.8), Анна (4.5), Вера (4.5)]
Пример: Класс Date (упрощённая дата)
Сравнение дат в формате ГГГГ-ММ-ДД:
@total_ordering
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __eq__(self, other):
if not isinstance(other, Date):
return NotImplemented
return (self.year, self.month, self.day) == (other.year, other.month, other.day)
def __lt__(self, other):
if not isinstance(other, Date):
return NotImplemented
return (self.year, self.month, self.day)
def __str__(self):
return f"{self.year}-{self.month:02}-{self.day:02}"
d1 = Date(2023, 5, 10)
d2 = Date(2023, 6, 1)
print(d1
Методические рекомендации по проведению занятия
Подчеркните, что равенство (==) и идентичность (is) — разные вещи.
Объясните, почему важно проверять тип other с помощью isinstance.
Покажите, что без __eq__ даже list.index() или in работают некорректно.
Обсудите семантику сравнения: что значит «один ученик больше другого»? — это всегда зависит от контекста.
Демонстрируйте пользу @total_ordering: меньше кода, меньше ошибок.
Практические задания:
Реализуйте класс Book (название, автор, год издания). Сравнение — по году издания.
Дополните класс Fraction (из предыдущих занятий) методами сравнения на основе численного значения дроби.
Создайте класс Rectangle (ширина, высота). Сравнение — по площади. Реализуйте полный набор методов сравнения.
Используя @total_ordering, реализуйте класс Version для сравнения версий ПО: "1.2.3"
Магические методы сравнения — важный инструмент для создания логически целостных и удобных в использовании классов. Правильная их реализация делает код не только функциональным, но и интуитивно понятным, а также открывает доступ к мощным встроенным возможностям Python: сортировке, поиску, фильтрации и другим операциям, основанным на сравнении.
Освоение этой темы способствует формированию у обучающихся системного подхода к проектированию программных сущностей и пониманию принципов «протоколов» в Python.