Дандер-методы: __str__, __repr__, __len__, __add__ и другие

Магия Python: что скрывается за двойными подчёркиваниями? 🔮

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

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)

__str__ vs __repr__: как Python представляет объекты

Эти методы отвечают за строковое представление объекта, но с разными целями:

__str__ — для человека 👨💻

Используется функциями print() и str(). Должен быть понятным и читаемым.

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

    def __str__(self):
        return f"'{self.title}' by {self.author}"

book = Book("Python Tricks", "Dan Bader")
print(book)  # Выведет: 'Python Tricks' by Dan Bader

__repr__ — для программиста 💻

Используется при выводе в консоли и функцией repr(). Должен быть однозначным и, желательно, позволяющим воссоздать объект.

def __repr__(self):
    return f"Book(title='{self.title}', author='{self.author}')"

# В консоли:
>>> book
Book(title='Python Tricks', author='Dan Bader')

Золотое правило: если __str__ не определён, Python использует __repr__ как резервный вариант!


Измеряем и складываем: __len__ и __add__

__len__ — считаем элементы 📏

Вызывается функцией len():

class Playlist:
    def __init__(self, songs):
        self.songs = songs

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

playlist = Playlist(["Song1", "Song2"])
print(len(playlist))  # 2

__add__ — создаём новые объекты ➕

Позволяет складывать объекты через оператор +:

class BankAccount:
    def __init__(self, balance):
        self.balance = balance

    def __add__(self, other):
        return BankAccount(self.balance + other.balance)

acc1 = BankAccount(100)
acc2 = BankAccount(200)
result = acc1 + acc2  # Новый счёт с балансом 300!

Продвинутые дандер-методы для особых случаев

__getitem__ — доступ по индексу 📌

Делает объект итерируемым:

class Library:
    def __init__(self, books):
        self.books = books

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

lib = Library(["Book1", "Book2"])
print(lib[1])  # 'Book2'

__call__ — объект как функция 📞

Позволяет вызывать экземпляр как функцию:

class Counter:
    def __init__(self):
        self.count = 0

    def __call__(self):
        self.count += 1
        return self.count

counter = Counter()
print(counter())  # 1
print(counter())  # 2

Когда использовать дандер-методы?

  1. Когда стандартное поведение Python нужно адаптировать под ваш класс
  2. Для улучшения читаемости кода (например, obj1 + obj2 вместо obj1.add(obj2))
  3. Для интеграции с Python-экосистемой (работа с len(), print() и т.д.)

Важно: не переусердствуйте! Иногда явный метод (например, .get_length()) лучше магического.


Практическая магия: пример класса "Таймер" ⏱️

class Timer:
    def __init__(self, seconds):
        self.seconds = seconds

    def __add__(self, other):
        return Timer(self.seconds + other.seconds)

    def __str__(self):
        mins, secs = divmod(self.seconds, 60)
        return f"{mins:02d}:{secs:02d}"

    def __repr__(self):
        return f"Timer({self.seconds})"

t1 = Timer(65)
t2 = Timer(120)
print(t1 + t2)  # 03:05

Этот пример объединяет несколько дандер-методов для создания интуитивно понятного интерфейса!


Куда двигаться дальше?

  1. Изучите другие дандер-методы: __eq__, __lt__ для сравнений
  2. Посмотрите, как работают __enter__/__exit__ для контекстных менеджеров
  3. Экспериментируйте! Создайте свой класс, который ведёт себя как встроенный тип Python

Для погружения в тему рекомендую видео Данилы Бежина про ООП в Python: https://www.youtube.com/@DanilaBezhin

Скрыть рекламу навсегда

🌱 Индвидидулаьные занятия

Индивидуальные онлайн-занятия по программированию для детей и подростков

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

🚀 Записаться на занятие