Ответ
Магические методы, также известные как "dunder" методы (от "double underscore" — двойное подчеркивание), — это специальные методы в Python, имена которых начинаются и заканчиваются двойным подчеркиванием (например, __init__
, __str__
). Они позволяют классам реализовывать определенные протоколы и переопределять поведение встроенных операций и функций.
Назначение: Dunder методы используются для:
- Операторной перегрузки: Изменение поведения стандартных операторов (например,
+
,-
,==
,[]
) для пользовательских объектов. - Реализации протоколов: Позволяют объектам вести себя как контейнеры, итераторы, числовые типы и т.д., интегрируясь с функциями Python (например,
len()
,str()
,for...in
). - Управления жизненным циклом объекта: Инициализация, удаление, создание.
Основные категории и примеры:
-
Инициализация и удаление объектов:
__new__(cls, ...)
: Вызывается для создания нового экземпляра класса.__init__(self, ...)
: Конструктор, инициализирует созданный объект.__del__(self)
: Деструктор, вызывается при удалении объекта (не гарантировано).
-
Строковое представление:
__str__(self)
: Определяет "официальное" строковое представление объекта, используемое функциейstr()
иprint()
. Должно быть читабельным для пользователя.__repr__(self)
: Определяет "неофициальное" строковое представление, используемое функциейrepr()
и в интерактивной консоли. Должно быть однозначным и, по возможности, позволять воссоздать объект.
-
Сравнение объектов (операторы сравнения):
__eq__(self, other)
:self == other
__ne__(self, other)
:self != other
__lt__(self, other)
:self < other
__le__(self, other)
:self <= other
__gt__(self, other)
:self > other
__ge__(self, other)
:self >= other
-
Контейнерные протоколы (доступ к элементам):
__len__(self)
:len(self)
__getitem__(self, key)
:self[key]
(доступ по индексу/ключу)__setitem__(self, key, value)
:self[key] = value
__delitem__(self, key)
:del self[key]
__contains__(self, item)
:item in self
-
Арифметические операции:
__add__(self, other)
:self + other
__sub__(self, other)
:self - other
__mul__(self, other)
:self * other
- И многие другие (
__truediv__
,__floordiv__
,__mod__
,__pow__
и т.д.).
Пример использования:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
"""Представление для разработчика."""
return f"Point(x={self.x}, y={self.y})"
def __str__(self):
"""Представление для пользователя."""
return f"({self.x}, {self.y})"
def __add__(self, other):
"""Перегрузка оператора сложения для сложения двух точек."""
if isinstance(other, Point):
return Point(self.x + other.x, self.y + other.y)
raise TypeError("Можно складывать только с объектом Point")
def __eq__(self, other):
"""Перегрузка оператора равенства."""
if isinstance(other, Point):
return self.x == other.x and self.y == other.y
return NotImplemented # Позволяет другому объекту попробовать сравнение
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = Point(1, 2)
print(p1) # Вызывает __str__: (1, 2)
print(repr(p1)) # Вызывает __repr__: Point(x=1, y=2)
p_sum = p1 + p2
print(f"Сумма точек: {p_sum}") # (4, 6)
print(f"p1 == p2: {p1 == p2}") # False
print(f"p1 == p3: {p1 == p3}") # True