# Домашнє завдання · Модулі й пакети

> Лекція: [lecture.html](lecture.html) · Практика: [practice.ipynb](practice.ipynb) · Тест: [quiz.html](quiz.html)

Це перше завдання, у якому ти працюєш **не в одному файлі**. Заведи для нього окрему теку —
хай буде `dz16/` — і всі файли складай у неї. Термінал відкривай саме в цій теці:
шлях пошуку модулів починається з неї.

---

## 🟢 Рівень 1 — База

Розклади маленьку програму на два файли.

1. Створи модуль `perevodyach.py` з константою `KURS = 41.5` і двома функціями:
   `v_hryvni(usd)` і `v_dolary(uah)`. Обидві округлюють результат до копійок.
2. Створи `main.py`, який імпортує модуль **трьома різними формами** (у трьох окремих
   рядках із коментарем, яка це форма) і друкує результат кожної.
3. Додай у `main.py` перевірку `assert`, що переведення туди й назад повертає
   початкове число з точністю до копійки.
4. Запусти: `python3 main.py`. Подивись, чи з'явилася тека `__pycache__`, і поясни
   у коментарі, для якого саме з двох файлів вона зроблена.

**Зроблено, якщо:** `python3 main.py` відпрацьовує без помилок, друкує три результати
й повідомлення про пройдений `assert`, а в коментарі написано, чому в `__pycache__`
лежить `perevodyach`, а не `main`.

---

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

Навчи модуль поводитися по-різному в двох ролях.

1. Додай у кінець `perevodyach.py` блок `if __name__ == "__main__":` з короткою
   демонстрацією: переведи 100 доларів і надрукуй результат.
2. Перевір обидва сценарії й запиши спостереження у файл `sposterezhennya.md`:
   - `python3 perevodyach.py` — що надрукувалось;
   - `python3 main.py` — чи з'явилась демонстрація;
   - додай на верхній рівень `perevodyach.py` рядок `print("модуль завантажено")`
     **поза** захисною умовою й повтори обидва запуски.
3. Поясни своїми словами, чому третій пункт — це саме та проблема, яку розв'язує
   захисна умова.

**Зроблено, якщо:** у `sposterezhennya.md` є чотири блоки виводу (два сценарії × до і після
додавання рядка) і абзац пояснення, у якому названо значення `__name__` в обох випадках.

---

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

Збери пакет і власноруч зламай його циклічним імпортом.

1. Перетвори свій код на пакет:

   ```
   dz16/
   ├── main.py
   └── finansy/
       ├── __init__.py
       ├── kursy.py        # KURS і функції переведення
       └── zvity.py        # форматування звіту
   ```

2. Зроби в `finansy/__init__.py` **фасад**: перетягни туди `v_hryvni`, щоб із `main.py`
   працювало `from finansy import v_hryvni` — без згадки про `kursy`.
3. Тепер навмисно створи цикл: хай `kursy.py` на верхньому рівні імпортує `zvity`
   і використовує його константу, а `zvity.py` — імпортує `kursy` й використовує `KURS`.
   Запусти й **збережи traceback** у `cykl.md`.
4. Виправ цикл **двома різними способами** й заміряй, чим вони відрізняються:
   - винести спільну константу в третій модуль `spilne.py`;
   - перенести один із імпортів усередину функції.
5. У `cykl.md` напиши, який спосіб ти лишиш у коді й чому. Наведи щонайменше два
   аргументи на користь свого вибору.

**Зроблено, якщо:** у `cykl.md` є (а) traceback зі словами `partially initialized module`,
(б) код обох виправлень, (в) абзац із двома аргументами; при цьому `python3 main.py`
відпрацьовує без помилок у фінальній версії, а `from finansy import v_hryvni` працює.

---

## Підказки

- **Не вгадуй, звідки взявся модуль** — надрукуй `модуль.__file__`. Один рядок економить
  пів години, коли «імпортується щось не те».
- **Порядок у циклі має значення.** Перш ніж дивитись на traceback, спробуй передбачити
  на папері, у якому порядку виконаються тіла модулів. Ключ до відповіді — момент, коли
  запис з'являється в `sys.modules`.
- **Фасад в `__init__.py`** — це звичайний імпорт, записаний у файлі пакета. Подумай,
  який саме рядок туди покласти, щоб ім'я стало доступним як `finansy.v_hryvni`.
- **Якщо `python3 main.py` каже `ModuleNotFoundError: No module named 'finansy'`** —
  ти стоїш не в тій теці. Зроби `pwd` і `ls`: `finansy/` має бути видно поруч із `main.py`.
- Тека `__pycache__` у домашню роботу не здається — це похідні файли. Якщо здаєш через git,
  додай її в `.gitignore`.
