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

Наслідування й композиція

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


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

Побудуй власну гілку ієрархії на три рівні й доведи, що ланцюжок super() працює наскрізь.

  1. Візьми з практики базовий клас Видання (назва, рік, методи опис і вік).
  2. Додай Журнал(Видання) з номером випуску. Його опис має кликати super().опис(), а не складати рядок з нуля.
  3. Додай Стаття(Журнал) з автором і сторінкою. Її опис теж кличе super().опис().
  4. Створи одну статтю й надрукуй: її опис(), її __dict__ і Стаття.__mro__.

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


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

Та сама предметна область, але тепер вимога змінюється — і треба показати, що наслідування її не тримає, а композиція тримає.

  1. Спершу наслідуванням. Напиши три класи: ПаперовеВидання(Видання), АудіоВидання(Видання), ЕлектроннеВидання(Видання), у кожного свій як_видати(). Створи по одному обʼєкту.
  2. Тепер нова вимога: «книга, яку читач узяв на папері, наступного тижня має стати доступною ще й файлом — той самий обʼєкт каталогу, той самий інвентарний номер». Спробуй виконати її, не створюючи новий обʼєкт. Запиши в коментарі, чому не виходить.
  3. Перепиши на композицію. Один клас Позиція (назва, рік, автор, носій, інвентарний_номер) і три маленькі класи-носії Папір, Аудіо, Файл, у кожного свій як_видати(). Позиція.як_видати() делегує роботу носію.
  4. Заведи одну позицію на папері, запамʼятай її id() та інвентарний номер, зміни носій на Файл() і перевір те й те ще раз.

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


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

Реалізуй пошук методу самостійно й знайди межу, за якою Python здається.

  1. Напиши функцію мій_mro(клас), яка будує лінеаризацію самостійно, без звертання до клас.__mro__. Дозволено користуватися лише клас.__bases__. Три правила лінеаризації: клас іде раніше за будь-якого свого предка; предки зберігають той порядок, у якому записані в дужках; кожен клас у списку рівно один раз.
  2. Перевір мій_mro щонайменше на пʼятьох ієрархіях: лінійний ланцюжок із трьох класів, ромб, «подвійний ромб» (два ромби один над одним), клас без явних базових, і клас, що успадковує два незалежні дерева.
  3. Знайди ієрархію, для якої Python відмовляється будувати MRO, і спіймай TypeError із текстом про неможливість лінеаризації. Поясни в коментарі, яке саме з трьох правил у ній суперечить іншому.
  4. На основі мій_mro напиши мій_getattr(обʼєкт, імʼя), яка шукає атрибут спершу в обʼєкт.__dict__, потім по класах, і кидає AttributeError із таким самим текстом, як у Python.

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


Підказки