Магические методы (или dunder methods – от double underscore) — это специальные методы, имя которых начинается и заканчивается двумя подчеркиваниями, например, __init__, __str__, __add__. Они позволяют встроить экземпляры собственных классов в синтаксис и поведение Python: определять реакцию на арифметические операции, сравнения, преобразование в строки, работу с протоколами коллекций и т.д.
Пример:
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) # Вызовет v1.__add__(v2), вернет Vector(4, 6)
Если не реализовать
__eq__в собственном классе, как будут сравниваться его экземпляры между собой оператором==?
Ответ: По умолчанию оператор == сравнивает объекты по идентичности (адресу в памяти, аналогично оператору is), если не переопределить магический метод __eq__.
class A: pass print(A() == A()) # False, хотя объекты "кажутся одинаковыми"
История
В проекте, где нужно было сравнивать структуры графа, не реализовали метод __eq__. Из-за этого при проверке "уже добавлен ли узел" получался некорректный результат, так как оператор == сравнивал объекты по id, а не по содержимому.
История
При написании REST API сериализировали объект в строку для лога через str(obj), но забыли определить __str__. В результате выводился нечитаемый текст <MyObj object at 0x...>, что затруднило диагностику проблем.
История
В библиотеке для математических вычислений реализовали только __add__, но забыли про __iadd__ для оператора +=. Как следствие, выражение v += w работало не как ожидалось (создавался новый объект, не обновлялся старый), что привело к утечкам памяти в сложном вычислениях.