← Назад к вопросам

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

2.0 Middle🔥 61 комментариев
#Python

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Магические методы (Dunder Methods) в Python

Определение

Магические методы (Magic Methods) или Dunder Methods (двойные подчеркивания) — это специальные методы в Python, которые начинаются и заканчиваются двойным подчеркиванием __. Они вызываются автоматически в определенных ситуациях.

Примеры: __init__, __str__, __repr__, __add__

Основные магические методы

1. __init__ (Конструктор)

class TestUser:
    def __init__(self, name, email):
        self.name = name
        self.email = email

user = TestUser("Alice", "alice@test.com")  # Вызывает __init__

2. __str__ (Строковое представление для пользователя)

class TestResult:
    def __init__(self, test_name, passed):
        self.test_name = test_name
        self.passed = passed
    
    def __str__(self):
        status = "PASSED" if self.passed else "FAILED"
        return f"{self.test_name}: {status}"

result = TestResult("test_login", True)
print(result)  # Вызывает __str__
# Вывод: test_login: PASSED

3. __repr__ (Представление для разработчика)

class TestCase:
    def __init__(self, test_id):
        self.test_id = test_id
    
    def __repr__(self):
        return f"TestCase(test_id={self.test_id})"

tc = TestCase("TC001")
print(repr(tc))  # TestCase(test_id=TC001)
print([tc])      # [TestCase(test_id=TC001)]

4. __len__ (Длина объекта)

class TestSuite:
    def __init__(self, tests):
        self.tests = tests
    
    def __len__(self):
        return len(self.tests)

suite = TestSuite(["test1", "test2", "test3"])
print(len(suite))  # 3

5. __getitem__ (Доступ по индексу)

class TestResults:
    def __init__(self, results):
        self.results = results
    
    def __getitem__(self, index):
        return self.results[index]

results = TestResults(["PASS", "FAIL", "PASS"])
print(results[0])  # PASS
print(results[1])  # FAIL

6. __setitem__ (Установка значения по индексу)

class TestScores:
    def __init__(self):
        self.scores = {}
    
    def __setitem__(self, test_id, score):
        self.scores[test_id] = score

scores = TestScores()
scores["TC001"] = 95  # Вызывает __setitem__
print(scores.scores)  # {"TC001": 95}

7. __contains__ (Оператор in)

class TestRegistry:
    def __init__(self, test_ids):
        self.test_ids = test_ids
    
    def __contains__(self, test_id):
        return test_id in self.test_ids

registry = TestRegistry(["TC001", "TC002", "TC003"])
if "TC001" in registry:  # Вызывает __contains__
    print("Test found")

8. Арифметические операторы

class TestScore:
    def __init__(self, value):
        self.value = value
    
    def __add__(self, other):
        return TestScore(self.value + other.value)
    
    def __sub__(self, other):
        return TestScore(self.value - other.value)
    
    def __mul__(self, number):
        return TestScore(self.value * number)
    
    def __truediv__(self, number):
        return TestScore(self.value / number)

score1 = TestScore(100)
score2 = TestScore(80)
result = score1 + score2  # Вызывает __add__

9. Операторы сравнения

class User:
    def __init__(self, user_id):
        self.user_id = user_id
    
    def __eq__(self, other):
        return self.user_id == other.user_id
    
    def __lt__(self, other):
        return self.user_id < other.user_id
    
    def __le__(self, other):
        return self.user_id <= other.user_id
    
    def __gt__(self, other):
        return self.user_id > other.user_id

user1 = User(1)
user2 = User(2)
print(user1 == user2)  # False
print(user1 < user2)   # True

10. __call__ (Объект как функция)

class TestExecutor:
    def __init__(self, test_name):
        self.test_name = test_name
    
    def __call__(self, *args, **kwargs):
        print(f"Executing {self.test_name}")
        return True

executor = TestExecutor("test_login")
result = executor()  # Вызывает __call__
# Вывод: Executing test_login

11. __enter__ и __exit__ (Context Manager)

class DatabaseConnection:
    def __enter__(self):
        print("Opening connection")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Closing connection")
        return False

with DatabaseConnection() as db:
    print("Using connection")
# Вывод:
# Opening connection
# Using connection
# Closing connection

12. __iter__ (Итератор)

class TestQueue:
    def __init__(self, tests):
        self.tests = tests
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.tests):
            raise StopIteration
        result = self.tests[self.index]
        self.index += 1
        return result

queue = TestQueue(["test1", "test2", "test3"])
for test in queue:
    print(test)
# Выведет: test1, test2, test3

13. __del__ (Деструктор)

class TestEnvironment:
    def __init__(self, name):
        self.name = name
        print(f"Creating {name}")
    
    def __del__(self):
        print(f"Destroying {self.name}")

env = TestEnvironment("test_env")
del env  # Вызывает __del__

Таблица основных магических методов

МетодИспользованиеПример
__init__Конструкторobj = Class()
__str__Строка для пользователяprint(obj)
__repr__Строка для разработчикаrepr(obj)
__len__Длинаlen(obj)
__getitem__По индексуobj[0]
__setitem__Установкаobj[0] = value
__contains__Проверкаitem in obj
__add__Сложениеobj1 + obj2
__sub__Вычитаниеobj1 - obj2
__call__Как функцияobj()
__enter__Начало контекстаwith obj:
__exit__Конец контекстаwith obj:
__iter__Итераторfor x in obj:
__eq__Равноobj1 == obj2
__lt__Меньшеobj1 < obj2

Практический пример для QA

class TestReport:
    def __init__(self, name, total, passed):
        self.name = name
        self.total = total
        self.passed = passed
    
    def __str__(self):
        return f"{self.name}: {self.passed}/{self.total}"
    
    def __repr__(self):
        return f"TestReport({self.name}, {self.total}, {self.passed})"
    
    def __len__(self):
        return self.total
    
    def __add__(self, other):
        return TestReport(
            f"{self.name} + {other.name}",
            self.total + other.total,
            self.passed + other.passed
        )

report1 = TestReport("Suite1", 10, 9)
report2 = TestReport("Suite2", 5, 5)

print(report1)  # Suite1: 9/10
print(len(report1))  # 10
print(report1 + report2)  # Suite1 + Suite2: 14/15

Резюме

Магические методы позволяют:

  • Переопределять встроенные операции (+, -, ==, <)
  • Интегрировать объекты в Python стандартные функции
  • Создавать более интуитивный API
  • Реализовать context managers и итераторы

Используйте их для создания удобных интерфейсов в тестовом коде.