Тест самоперевірки

Декоратори

Обери відповідь — і одразу побачиш пояснення. Помилитись тут корисніше, ніж на іспиті.

← до лекції
Відповіді0 / 8   правильних: 0
Питання 1 / 8

Рядок @таймер стоїть над def підсумок. Коли саме виконується сам таймер?

Чому так. Рядок @таймер — це скорочення для підсумок = таймер(підсумок), і виконується він рівно там, де написаний: одразу після того, як def створив функцію. При кожному виклику працює вже обгортка, яку таймер повернув, а не сам таймер.
Питання 2 / 8

У декораторі забули останній рядок обгортки — return результат. Що побачить той, хто викликає задекоровану функцію?

Чому так. Функція без return повертає None — правило з теми 14 діє й для обгортки. Жодної помилки не буде: обчислення відбулись, значення просто нікуди не пішло. Саме тому такий баг шукають у самій функції, де його немає.
Питання 3 / 8

Зовнішня функція зробити_множник(2) уже завершилась. Чому внутрішня функція досі бачить двійку?

Чому так. Кадр справді знищується — правило теми 15 не скасоване. Але захоплене імʼя Python кладе в окрему комірку (cell), яку тримає сама функція через __closure__. Комірка живе, поки жива функція, — і кадр тут ні до чого. Глобальною двійка не стає: у globals() її немає, а в кожної виготовленої функції комірка своя.
Питання 4 / 8

Задекорували функцію без functools.wraps. Що з нею станеться?

Чому так. Імʼя підсумок тепер вказує на обгортку, тож підсумок.__name__ дорівнює ʼобгорткаʼ, докстрінг — None, а help() показує (*args, **kwargs). Поведінка при цьому правильна — саме тому проблему й помічають пізно: у журналі помилок або в редакторі, а не під час роботи.
Питання 5 / 8

Рядок @повторити(спроб=3) над функцією. Що саме отримує функція завантажити?

Чому так. Розгортка це показує: завантажити = повторити(спроб=3)(завантажити). Дві пари дужок поспіль — два різні виклики. повторити — не декоратор, а виробник декораторів; саме тому в неї три рівні вкладеності, а не два. Якщо написати @повторити без дужок, помилки в цьому рядку не буде — функція справді поїде в параметр спроб, і зламається все пізніше.
Питання 6 / 8

В інтерактиві лекції 60 замовлень і maxsize=4 давали 18 справжніх обчислень і 42 влучання. Що станеться, якщо поставити maxsize=1?

Чому так. Кеш на одне місце тримає лише останнє місто, а замовлення чергуються — тому потрібне значення встигає вилетіти. На 200 замовленнях влучань лишається 17% замість 96%. Кеш, менший за кількість різних запитів, — це не «маленький кеш», а майже жодного. Помилки при цьому немає: maxsize може бути будь-яким.
Питання 7 / 8

Над функцією стоять два декоратори: @логувати згори, @таймер знизу. Хто з них опиниться найближче до самої функції?

Чому так. Розгортка: підсумок = логувати(таймер(підсумок)). Внутрішні дужки рахуються першими, а це саме нижній декоратор. Тому застосування йде знизу вгору, а виконання при виклику — навпаки, ззовні всередину: першим спрацює логувати.
Питання 8 / 8

Функція вартість(міста) задекорована @lru_cache. Виклик вартість(["Київ", "Львів"]) падає з TypeError: unhashable type: 'list'. Де саме сталася помилка?

Чому так. Кеш усередині — звичайний словник, а ключ у ньому складається з аргументів виклику. Зі словників (тема 08) ми знаємо: ключем може бути лише хешований обʼєкт. Обгортка намагається зібрати ключ ще до виклику справжньої функції — тому тіло навіть не починає виконуватись. Ліки: передати кортеж замість списку.