Магические методы: __str__, __repr__, __eq__

Магические методы: str, repr, eq

Python использует специальные методы с двойными подчёркиваниями (__name__) для интеграции объектов со встроенными операциями языка. Их называют магическими методами или dunder-методами (от double underscore). Определив их в классе, вы учите Python, как работать с вашими объектами.

str: читаемое строковое представление

Когда вы вызываете print(obj) или str(obj), Python ищет метод __str__. Если его нет — выводится что-то вроде <__main__.Dog object at 0x7f...>. Бесполезно для отладки:

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

    def __str__(self):
        return f"Point({self.x}, {self.y})"

p = Point(3, 4)
print(p)           # Point(3, 4)
print(str(p))      # Point(3, 4)
print(f"Точка: {p}")  # Точка: Point(3, 4)

__str__ возвращает строку, понятную пользователю.

repr: техническое представление

__repr__ (representation) — техническое описание, полезное для разработчика. Вызывается в REPL и через repr(). Соглашение: строка, которую можно скопировать и выполнить, чтобы воссоздать объект:

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

    def __repr__(self):
        return f"Point({self.x!r}, {self.y!r})"

    def __str__(self):
        return f"({self.x}, {self.y})"

p = Point(3, 4)
print(repr(p))   # Point(3, 4)  — техническое
print(str(p))    # (3, 4)       — пользовательское

lst = [Point(1, 2), Point(3, 4)]
print(lst)   # [Point(1, 2), Point(3, 4)] — в контейнерах Python использует __repr__

Если __str__ не определён, Python использует __repr__ везде. Если нужен только один — определяйте __repr__.

eq: сравнение объектов

По умолчанию == сравнивает объекты по идентичности (is): два разных объекта с одинаковыми данными не равны:

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

p1 = Point(3, 4)
p2 = Point(3, 4)

print(p1 == p2)   # False — разные объекты в памяти

Определив __eq__, вы задаёте логику сравнения:

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

    def __eq__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return self.x == other.x and self.y == other.y

p1 = Point(3, 4)
p2 = Point(3, 4)
p3 = Point(1, 2)

print(p1 == p2)   # True
print(p1 == p3)   # False
print(p1 == "не точка")   # False (NotImplemented → Python пробует обратное)

NotImplemented (не NotImplementedError) — специальное значение, говорящее Python: «я не умею сравнивать с этим типом, попробуй другую сторону».

Другие полезные dunder-методы

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 __len__(self):              # len(v)
        return 2  # вектор двумерный

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)   # Vector(4, 6)
print(len(v1))   # 2

Таблица популярных dunder-методов:

МетодКогда вызывается
__str__str(obj), print(obj), f-строки
__repr__repr(obj), REPL, контейнеры
__eq__obj == other
__len__len(obj)
__add__obj + other
__lt__obj < other
__contains__x in obj

Итог

  • __str__ — читаемое строковое представление для пользователя.
  • __repr__ — техническое представление для разработчика; используется в REPL и контейнерах.
  • __eq__ — логика сравнения через ==; возвращайте NotImplemented для неподдерживаемых типов.
  • Dunder-методы интегрируют объекты с операторами и встроенными функциями Python.

В следующем уроке разберём инкапсуляцию и приватные атрибуты — как защитить данные объекта от нежелательного изменения снаружи.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике