← Назад к вопросам
Как вызываются магические (dunder) методы?
1.2 Junior🔥 191 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое магические методы
Магические (dunder) методы — это специальные методы в Python, имена которых начинаются и заканчиваются двойным подчёркиванием (__method__). Они позволяют переопределять поведение встроенных операций для пользовательских объектов и делают классы более "pythonic".
Вызов магических методов
Магические методы вызываются не напрямую (хотя технически это возможно), а автоматически интерпретатором Python при выполнении определённых операций:
1. Инициализация и конструктор
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __new__(cls, x, y):
# Вызывается перед __init__ для создания экземпляра
return super().__new__(cls)
# Вызов через конструктор
p = Point(1, 2) # __new__ → __init__
2. Арифметические операции
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other): # v1 + v2
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other): # v1 - v2
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar): # v * 2
return Vector(self.x * scalar, self.y * scalar)
def __truediv__(self, scalar): # v / 2
return Vector(self.x / scalar, self.y / scalar)
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2 # Вызывает __add__
v4 = v1 * 2 # Вызывает __mul__
3. Сравнение
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other): # ==
return self.age == other.age
def __lt__(self, other): # <
return self.age < other.age
def __le__(self, other): # <=
return self.age <= other.age
def __gt__(self, other): # >
return self.age > other.age
def __ge__(self, other): # >=
return self.age >= other.age
def __ne__(self, other): # !=
return self.age != other.age
p1 = Person("Alice", 30)
p2 = Person("Bob", 25)
result = p1 > p2 # Вызывает __gt__
4. Строковое представление
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def __str__(self): # str(), print()
return f"{self.brand} {self.model}"
def __repr__(self): # repr(), интерактивный режим
return f"Car('{self.brand}', '{self.model}')"
car = Car("Toyota", "Camry")
print(car) # Вызывает __str__
print(repr(car)) # Вызывает __repr__
5. Доступ к элементам (индексация и слайсинг)
class CustomList:
def __init__(self, items):
self.items = items
def __getitem__(self, index): # obj[key]
return self.items[index]
def __setitem__(self, index, value): # obj[key] = value
self.items[index] = value
def __delitem__(self, index): # del obj[key]
del self.items[index]
def __len__(self): # len()
return len(self.items)
cl = CustomList([1, 2, 3])
value = cl[0] # Вызывает __getitem__
cl[0] = 10 # Вызывает __setitem__
size = len(cl) # Вызывает __len__
6. Вызываемость объекта
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x): # obj(args)
return x * self.factor
mult = Multiplier(3)
result = mult(5) # Вызывает __call__, возвращает 15
7. Контекстный менеджер
class FileManager:
def __init__(self, filename):
self.filename = filename
def __enter__(self): # with statement
self.file = open(self.filename)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
with FileManager('data.txt') as f:
# __enter__ вызывается здесь
data = f.read()
# __exit__ вызывается здесь
8. Атрибуты
class DynamicAttributes:
def __getattr__(self, name): # obj.attr (если нет атрибута)
return f"Атрибут {name} не найден"
def __setattr__(self, name, value): # obj.attr = value
super().__setattr__(name, value)
def __delattr__(self, name): # del obj.attr
super().__delattr__(name)
def __getattribute__(self, name): # Вызывается для ЛЮБОГО атрибута
return super().__getattribute__(name)
obj = DynamicAttributes()
obj.x = 10 # Вызывает __setattr__
value = obj.x # Вызывает __getattribute__
9. Итераторы и генераторы
class CountUp:
def __init__(self, max):
self.max = max
self.current = 0
def __iter__(self): # iter()
return self
def __next__(self): # next()
if self.current < self.max:
self.current += 1
return self.current
raise StopIteration
for num in CountUp(3): # Вызывает __iter__ и __next__
print(num)
10. Отправка (dispatch)
class Matrix:
def __hash__(self): # hash()
return id(self)
def __bool__(self): # bool(), if obj
return True
def __sizeof__(self): # sys.getsizeof()
return 128
m = Matrix()
if m: # Вызывает __bool__
print("Объект истинен")
Ключевые моменты
- Автоматический вызов: интерпретатор вызывает методы за кулисами, вы пишете операции как обычно
- Не вызывайте напрямую: избегайте
obj.__add__(other), используйтеobj + other - Обратная совместимость:
__radd__,__rsub__для операций справа2 * obj - Порядок вычислений: Python сначала ищет метод левого операнда, потом правого
- Исключения: некоторые методы можно вызвать напрямую (
__init__,__new__), но обычно это не требуется
Магические методы — это то, что делает Python таким выразительным и гибким языком!