Яндекс.Метрика
Услуги Портфолио Контакты БлогНовости +7 (800) 511‑32‑27 Обсудить проект
Статьи

Что такое магические методы в Python

14 декабря 2022·Обновлено 19 августа 2026·8 мин чтения
Дмитрий Лукьянов
Автор материалаДмитрий ЛукьяновBackend-разработчик, YuSMP Group
Профиль автора
Что такое магические методы в Python

Магические методы 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 подойдёт для вашего продукта.

Нужны разработчики в команду?

Подберём инженеров нужного стека под ваш проект — быстрый старт.

Обсудить команду