Модульні уроки (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__, ви також безкоштовно отримуєте boolean: об’єкт
з len() == 0 стає помилковим.
Інші корисні дандери (огляд)
__add__(self, other)→ перевизначає+__lt__,__le__,__gt__,__ge__→ оператори порівняння__contains__(self, item)→ підтримуєitem in self__iter__+__next__→ робить об'єкт ітерованим__getitem__(self, key)→ підтримуєself[key]__hash__→ має бути ключем dict / елементом набору
Ваша черга
Визначте `Money` за допомогою __init__(self, сума, валюта) і __str__, який повертає `f'{amount} {currency}''`. Створіть `s = Money(42, 'EUR')` і обчисліть `str(s)`.
Показати підказку
f-рядок у __str__.
Рішення доступне після 3 спроб
Повторна вправа
Визначте `Pair` за допомогою __init__(self, a, b) і __eq__ на основі структурного порівняння (a, b). Оцініть `Pair(1, 2) == Pair(1, 2)`.
Показати підказку
Порівняйте кортежі (self.a, self.b) == (other.a, other.b).
Рішення доступне після 3 спроб
Додатковий виклик
Визначте клас \`Книга\` з конструктором, який бере \`назву\` та \`автора\`. Визначте спеціальний метод \`__str__(self)\`, щоб він повертав рядок \`"Назва за автором"\` (наприклад, \`'1984 by George Orwell'\`). Створіть екземпляр книги та обчисліть \`str(book)\`.
Показати підказку
Використовуйте f"{self.title} від {self.author}" всередині def __str__(self):.
Рішення доступне після 3 спроб