Какие магические методы в Python вы знаете?

«Какие магические методы в Python вы знаете?» — вопрос из категории Python, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Python я активно использую магические методы (dunder methods) для создания интуитивных и Pythonic API. Вот основные категории:

1. Конструкторы и деструкторы:

class DatabaseConnection:
    def __init__(self, connection_string):
        self.conn = create_connection(connection_string)

    def __del__(self):
        if hasattr(self, 'conn'):
            self.conn.close()  # Гарантируем закрытие соединения

2. Строковое представление:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Vector({self.x}, {self.y})"  # Для пользователя

    def __repr__(self):
        return f"Vector(x={self.x}, y={self.y})"  # Для разработчика

3. Контейнеры и последовательности:

class CustomList:
    def __init__(self, items):
        self._items = list(items)

    def __len__(self):
        return len(self._items)

    def __getitem__(self, index):
        return self._items[index]

    def __setitem__(self, index, value):
        self._items[index] = value

    def __contains__(self, item):
        return item in self._items

4. Операторы:

class Money:
    def __init__(self, amount, currency):
        self.amount = amount
        self.currency = currency

    def __add__(self, other):
        if self.currency != other.currency:
            raise ValueError("Валюты должны совпадать")
        return Money(self.amount + other.amount, self.currency)

    def __eq__(self, other):
        return (self.amount == other.amount and 
                self.currency == other.currency)

5. Контекстные менеджеры:

class Timer:
    def __enter__(self):
        self.start = time.time()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.elapsed = time.time() - self.start
        print(f"Время выполнения: {self.elapsed:.2f} сек")

# Использование:
with Timer() as timer:
    # выполнение кода

6. Вызываемые объекты:

class Polynomial:
    def __init__(self, coefficients):
        self.coeffs = coefficients

    def __call__(self, x):
        return sum(c * (x ** i) for i, c in enumerate(self.coeffs))

poly = Polynomial([1, 2, 3])  # 1 + 2x + 3x²
result = poly(2)  # 1 + 4 + 12 = 17

В реальных проектах я чаще всего реализую __init__, __str__, __repr__, __eq__ и методы для контейнеров. Особенно полезны __enter__/__exit__ для работы с ресурсами и __call__ для создания функциональных объектов.