Магические методы Python (dunder-методы, от «double underscore» — двойное подчёркивание) — специальные методы класса, имя которых начинается и заканчивается двойным подчёркиванием: __add__, __str__, __init__. Python вызывает их автоматически в ответ на определённые операции — вам не нужно обращаться к ним напрямую.
Именно дандер-методы делают классы «питоничными»: позволяют перегружать операторы, делать объекты итерируемыми, вызываемыми, работать с with и len().
Справочная таблица: магические методы Python по категориям
| Категория | Метод | Когда вызывается |
|---|---|---|
| Инициализация | __init__(self, ...) | После создания объекта |
| Инициализация | __new__(cls, ...) | До __init__, создаёт экземпляр |
| Удаление | __del__(self) | При уничтожении объекта GC |
| Строки | __str__(self) | str(obj), print(obj) |
| Строки | __repr__(self) | repr(obj), отладчик |
| Арифметика | __add__(self, other) | a + b |
| Арифметика | __sub__(self, other) | a - b |
| Арифметика | __mul__(self, other) | a * b |
| Арифметика | __truediv__(self, other) | a / b |
| Арифметика | __mod__(self, other) | a % b |
| Арифметика | __pow__(self, other) | a ** b |
| Сравнение | __eq__(self, other) | a == b |
| Сравнение | __ne__(self, other) | a != b |
| Сравнение | __lt__(self, other) | a < b |
| Сравнение | __le__(self, other) | a <= b |
| Сравнение | __gt__(self, other) | a > b |
| Сравнение | __ge__(self, other) | a >= b |
| Контейнеры | __len__(self) | len(obj) |
| Контейнеры | __getitem__(self, key) | obj[key] |
| Контейнеры | __setitem__(self, key, v) | obj[key] = v |
| Контейнеры | __contains__(self, item) | x in obj |
| Контейнеры | __iter__(self) | for x in obj, iter(obj) |
| Вызов | __call__(self, ...) | obj(...) |
| Атрибуты | __getattr__(self, name) | Доступ к несуществующему атрибуту |
| Атрибуты | __setattr__(self, name, v) | Присваивание атрибута |
| Менеджер контекста | __enter__(self) | Вход в блок with |
| Менеджер контекста | __exit__(self, ...) | Выход из блока with |
Разбор ключевых методов с примерами кода
__add__ — перегрузка оператора +
__add__ вызывается, когда Python встречает оператор + между двумя объектами. Без переопределения складывать пользовательские объекты нельзя. Чтобы перегрузить другие операторы, используйте соответствующие методы: __sub__ для -, __mul__ для *, __truediv__ для /.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f'Vector({self.x}, {self.y})'
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
__new__ — создание экземпляра
В Java и C# объект создаётся оператором new явно. В Python __new__() вызывается неявно — до __init__(): сначала создаётся экземпляр, затем инициализируется.
class Employee:
def __new__(cls):
print("__new__ вызван — создаётся экземпляр")
return super().__new__(cls)
def __init__(self):
print("__init__ вызван — объект инициализируется")
self.name = 'Дмитрий'
emp = Employee()
# __new__ вызван — создаётся экземпляр
# __init__ вызван — объект инициализируется
Переопределять __new__ нужно редко — только при создании подклассов неизменяемых типов (int, str) или реализации паттерна Singleton.
__str__ и __repr__ — строковое представление
__str__ возвращает читаемое представление объекта для пользователя — вызывается через str() и print(). __repr__ — техническое представление для разработчика, используется в отладчике. Правило: вывод __repr__ должен позволять воссоздать объект.
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def __str__(self):
return f'{self.name}, зарплата: {self.salary} ₽'
def __repr__(self):
return f"Employee(name='{self.name}', salary={self.salary})"
emp = Employee('Дмитрий', 120000)
print(str(emp)) # Дмитрий, зарплата: 120000 ₽
print(repr(emp)) # Employee(name='Дмитрий', salary=120000)
__ge__ и __lt__ — операторы сравнения
Методы сравнения позволяют сопоставлять пользовательские объекты стандартными операторами. Каждый оператор соответствует своему методу: < → __lt__, <= → __le__, >= → __ge__, > → __gt__, == → __eq__.
class Distance:
def __init__(self, meters):
self.meters = meters
def __lt__(self, other):
return self.meters < other.meters
def __ge__(self, other):
return self.meters >= other.meters
d1 = Distance(100)
d2 = Distance(200)
print(d1 < d2) # True
print(d1 >= d2) # False
Совет: используйте декоратор @functools.total_ordering — достаточно определить __eq__ и один метод сравнения, Python сгенерирует остальные автоматически.
__call__ — вызываемый объект
__call__ делает экземпляр класса вызываемым как обычную функцию. Полезен при реализации замыканий, декораторов, стейтфул-функторов.
class Person:
def __call__(self, other):
return f'Привет, {other}!'
alice = Person()
print(alice('Боб')) # Привет, Боб!
__enter__ и __exit__ — менеджер контекста
Python вызывает __enter__() при входе в блок with и __exit__() — при выходе (в том числе при исключении). Объект, реализующий оба метода, называется менеджером контекста — это стандартный способ управлять ресурсами: соединениями, файлами, транзакциями.
class DatabaseConnection:
def __init__(self, url):
self.url = url
def __enter__(self):
print(f'Подключение к {self.url}')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(f'Закрытие соединения с {self.url}')
return False # не подавляем исключения
with DatabaseConnection('db://localhost') as conn:
print('Работаем с базой данных')
# Подключение к db://localhost
# Работаем с базой данных
# Закрытие соединения с db://localhost
Если __exit__ возвращает True, исключение внутри блока with подавляется. False или None — исключение всплывает дальше.
Часто задаваемые вопросы о магических методах Python
- Что такое магические методы Python?
- Это специальные методы класса с двойным подчёркиванием в имени —
__init__,__str__,__add__. Python вызывает их автоматически при определённых операциях: создании объекта, сложении, преобразовании в строку. Разработчик переопределяет их, чтобы задать кастомное поведение. - В чём разница между __str__ и __repr__?
__str__— читаемое представление для пользователя, используется вprint()иstr().__repr__— техническое представление для разработчика: отладчик, интерактивная консоль. Правило: вывод__repr__должен позволять воссоздать объект черезeval(repr(obj)).- Когда использовать __new__ вместо __init__?
__new__нужен редко: создание подклассов неизменяемых типов (int,str), реализация Singleton, управление пулом объектов. В большинстве задач достаточно__init__— он вызывается после__new__и инициализирует уже созданный экземпляр.- Зачем переопределять __eq__?
- По умолчанию
==сравнивает объекты по идентичности (адресу в памяти). Переопределив__eq__, задаёте сравнение по значению. Важно: без__hash__объект станет нехэшируемым и его нельзя добавить вsetили использовать как ключdict. - Как посмотреть все dunder-методы объекта?
- Вызовите
dir(obj)— он вернёт список всех атрибутов и методов включая магические. Фильтр только дандер-методов:[m for m in dir(obj) if m.startswith('__') and m.endswith('__')].
Итоги
Магические методы — один из ключевых механизмов Python, позволяющий создавать выразительные и идиоматичные классы. Понимание дандер-методов необходимо backend-разработчику: без них не обойтись при создании ORM, фреймворков и кастомных структур данных.
Python входит в технологический стек backend-разработки в YuSMP Group. Посмотрите примеры наших проектов или свяжитесь через форму контактов — расскажем, как Python подойдёт для вашего продукта.
Нужны разработчики в команду?
Подберём инженеров нужного стека под ваш проект — быстрый старт.




