Уроки модуля (3/4)
Специальные методы (дандер)
Специальные методы (называемые методами dunder, потому что они начинаются и заканчиваются
с двойным подчеркиванием: __name__) — это перехватчики, которые позволяют вашим объектам
интеграция с языком: текстовое представление, сравнение с ==,
поддержка len(), in, операторов и т. д.
Вы уже использовали один: __init__.
__str__ и __repr__
Они контролируют то, что отображается в print() и в REPL.
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__:
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()
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.
Ваша очередь
Определите `Money` с помощью __init__(self, sum,currency) и __str__, который возвращает `f'{amount} {currency}'`. Создайте `s = Money(42, 'EUR')` и оцените `str(s)`.
Показать подсказку
f-строка в __str__.
Решение доступно после 3 попыток
Обзор упражнения
Определите `Pair` с __init__(self, a, b) и __eq__ на основе структурного сравнения (a, b). Оцените `Пара(1, 2) == Пара(1, 2)`.
Показать подсказку
Сравните кортежи (self.a, self.b) == (other.a,other.b).
Решение доступно после 3 попыток
Дополнительная задача
Определите класс «Book» с конструктором, принимающим «title» и «author». Определите специальный метод \`__str__(self)\`, чтобы он возвращал строку \`"Название автора"\` (например, \`'1984 Джорджа Оруэлла'\`). Создайте экземпляр книги и оцените \`str(book)\`.
Показать подсказку
Используйте f"{self.title} от {self.author}" внутри def __str__(self):.
Решение доступно после 3 попыток