Домашнє завдання

Магічні методи

Працюємо з тим самим каталогом бібліотеки, що й у лекції. Усе роби в окремому файлі katalog.py або в новому зошиті — практику не редагуй, вона знадобиться для звірки.


рівень 1Рівень 1 — База

Збери клас Видання з повним набором методів і доведи assertами, що кожен із них справді викликається.

  1. Напиши Видання(назва, рік, сторінок) — три поля замість двох.
  2. Додай __repr__ (відтворюваний: Видання('Кобзар', 1840, 114)) і __str__ (людський: Кобзар (1840)).
  3. Додай __eq__ і __hash__ за всіма трьома полями — обовʼязково разом.
  4. Додай __len__, який повертає кількість сторінок.
  5. Створи три видання, з яких два мають однаковий вміст, і поклади всі три в множину.

Зроблено, якщо:


рівень 2Рівень 2 — Плюс

Тепер контейнер і власний менеджер контексту.

  1. Напиши клас Полиця, який тримає список видань і реалізує __len__, __getitem__, __iter__, __contains__ і __repr__.
  2. Додай __add__: полиця1 + полиця2 повертає нову полицю з усіма позиціями обох. Вихідні полиці не змінюються.
  3. Додай __lt__ для Видання (порядок за роком, потім за назвою) і метод Полиця.за_роком(), який повертає нову полицю з відсортованими позиціями.
  4. Напиши менеджер контексту Інвентаризація, який на вході запамʼятовує len(полиця), а на виході друкує, скільки позицій додали чи прибрали за час блоку, і записує різницю в атрибут зміна.

Зроблено, якщо:


рівень 3Рівень 3 — Виклик

Дослідження меж: що саме ламається, коли контракт порушено, і скільки це коштує.

  1. Зміряй ціну хешу. Зроби два класи з однаковим __eq__: у першого __hash__ рахується з кортежа полів, у другого — return 1 (формально контракт не порушено: рівні обʼєкти дають рівний хеш!). Заведи по 5000 різних видань кожного класу, поклади в множину й зміряй time.perf_counter() для побудови та для 5000 перевірок in.
  2. Поясни цифри. Запиши в коментарі, чому другий варіант повільніший і на скільки разів, спираючись на розділ про хеш-таблицю з теми 8: що відбувається, коли всі ключі потрапляють в одну комірку.
  3. Зламай обʼєкт зсередини множини. Візьми клас із коректним __hash__, поклади обʼєкт у множину, а потім зміни поле, від якого хеш залежить. Покажи assertами, що обʼєкт більше не знаходиться в множині — навіть за самим собою, — хоча len(множина) і далі дорівнює одиниці.
  4. Полагодь. Переробі клас так, щоб зламати його стало неможливо: поля тільки читаються (property без сетера або __slots__ плюс запис у __init__ через object.__setattr__), а «зміна» повертає новий обʼєкт методом з_роком(новий_рік).

Зроблено, якщо:


Підказки