Перейти к основному содержимому
Модуль 7 · Урок 3 из 427/36 в курсе~12 min
Уроки модуля (3/4)

Специальные методы (дандер)

Специальные методы (называемые методами dunder, потому что они начинаются и заканчиваются с двойным подчеркиванием: __name__) — это перехватчики, которые позволяют вашим объектам интеграция с языком: текстовое представление, сравнение с ==, поддержка len(), in, операторов и т. д.

Вы уже использовали один: __init__.

__str__ и __repr__

Они контролируют то, что отображается в print() и в REPL.

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

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

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

p = Punto(3, 4)
str(p)        # '(3, 4)'        — per umani
repr(p)       # 'Punto(3, 4)'   — per debugger / dev
print(p)      # '(3, 4)'
p             # Punto(3, 4)     in REPL → repr
[p, p]        # [Punto(3, 4), Punto(3, 4)]   — sempre repr nei contenitori

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

__eq__: переопределение ==

По умолчанию a == b сравнивает идентификаторы объектов (is), а не их содержимое. Для структурного сравнения определите __eq__:

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

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

Punto(1, 2) == Punto(1, 2)    # True
Punto(1, 2) == Punto(3, 4)    # False

Возврат NotImplemented (специальное ключевое слово, а не False!), когда типы несопоставимы, это правильная практика: Python попытается использовать __eq__ другого операнда.

__len__: поддержка len()

Python
class Cesto:
    def __init__(self):
        self.frutti = []

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

c = Cesto()
c.frutti.append("mela")
len(c)        # 1
bool(c)       # True (len > 0)

Определив __len__, вы также бесплатно получаете логическое значение: объект с len() == 0 становится ложным.

Другие полезные вещи (обзор)

  • __add__(self, other) → переопределяет +
  • __lt__, __le__, __gt__, __ge__ → операторы сравнения
  • __contains__(self, item) → поддерживает item in self
  • __iter__ + __next__ → делает объект итерируемым
  • __getitem__(self, key) → поддерживает self[key]
  • __hash__ → должен быть элементом dict/set.

Ваша очередь

Упражнение#python.m7.l3.e1
Попыток: 0Загрузка…

Определите `Money` с помощью __init__(self, sum,currency) и __str__, который возвращает `f'{amount} {currency}'`. Создайте `s = Money(42, 'EUR')` и оцените `str(s)`.

Загрузка редактора…
Показать подсказку

f-строка в __str__.

Решение доступно после 3 попыток

Обзор упражнения

Упражнение#python.m7.l3.e2
Попыток: 0Загрузка…

Определите `Pair` с __init__(self, a, b) и __eq__ на основе структурного сравнения (a, b). Оцените `Пара(1, 2) == Пара(1, 2)`.

Загрузка редактора…
Показать подсказку

Сравните кортежи (self.a, self.b) == (other.a,other.b).

Решение доступно после 3 попыток

Дополнительная задача

Упражнение#python.m7.l3.e3
Попыток: 0Загрузка…

Определите класс «Book» с конструктором, принимающим «title» и «author». Определите специальный метод \`__str__(self)\`, чтобы он возвращал строку \`"Название автора"\` (например, \`'1984 Джорджа Оруэлла'\`). Создайте экземпляр книги и оцените \`str(book)\`.

Загрузка редактора…
Показать подсказку

Используйте f"{self.title} от {self.author}" внутри def __str__(self):.

Решение доступно после 3 попыток