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

Спискові включення

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

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

цінник = [28.5, 32.0, 19.9, 145.0, 12.0]. Скільки елементів буде в кожному з двох списків: [ціна for ціна in цінник if ціна < 100] і [ціна if ціна < 100 else 100 for ціна in цінник]?

Чому так. Перший запис — фільтр: if у кінці вирішує, чи впустити елемент, і 145.0 не проходить — лишається 4. Другий — перетворення тернарним виразом: він нічого не викидає, а лише обирає, яке значення покласти, тому довжина завжди дорівнює довжині джерела — 5. Найчастіша помилка тут — вважати, що обидва записи фільтрують: вони збігаються лише на даних, де умову проходять усі.
Питання 2 / 8

У включенні [важка_функція(x) for x in дані if x > 0] у списку 1000 елементів, з яких умову проходять 10. Скільки разів викличеться важка_функція?

Чому так. Пишемо ми зліва направо, а виконується справа наліво: спершу джерело, потім умова, і лише потім вираз — тільки для тих елементів, які фільтр пройшли. Спокуслива відповідь «1000» походить від порядку читання: вираз стоїть першим у рядку, тому здається, що він і застосовується першим.
Питання 3 / 8

покупки = ['хліб', 'мед', 'сіль', 'мед', 'хліб']. Що поверне {len(назва) for назва in покупки}?

Чому так. Фігурні дужки з одним виразом (без двокрапки) дають множину, а множина не вміє тримати два однакові елементи — пʼять довжин злипаються у два різних значення. Щоб отримати словник, у виразі мала б стояти двокрапка: {назва: len(назва) …}. Жодного коду «прибрати дублікати» ми не писали — це властивість типу.
Питання 4 / 8

Що лежить у змінній результат після рядка результат = [print(назва) for назва in покупки], де в покупках пʼять елементів?

Чому так. Функція print друкує на екран, а повертає None — тож включення сумлінно збирає список із пʼятьох None. Надрукований текст збиває з пантелику: здається, що код «працює», хоча насправді він виділив памʼять під сміття. Потрібна дія, а не колекція — пиши звичайний for.
Питання 5 / 8

матриця = [[1, 2], [3, 4]]. Чому [значення for значення in рядок for рядок in матриця] не працює, хоча в ньому ті самі частини, що й у правильному записі?

Чому так. for-и читаються зліва направо, як вкладені цикли: зовні всередину. Найлівіший тут просить обходити рядок — імʼя, якого ще не існує, бо створює його наступний for. Спокуслива відповідь «просто інший порядок» хибна: коду не існує взагалі, він падає з NameError.
Питання 6 / 8

Після рядка квадрати = [ч ** 2 for ч in range(3)] ти пишеш print(ч). Що станеться?

Чому так. На відміну від звичайного for, де змінна після циклу лишається живою з останнім значенням, включення виконується у власній області видимості: імʼя існує тільки всередині дужок. Варіант «2» — це саме поведінка звичайного циклу (і поведінка включень у Python 2, яку вважали помилкою дизайну й виправили).
Питання 7 / 8

Чому запис [ціна for ціна in цінник if ціна < 100 else 0] падає з SyntaxError?

Чому так. У хвості включення стоїть фільтр — він уміє лише впустити елемент або ні, тому else йому нема куди подіти. Гілка else існує лише в тернарному виразі a if умова else b, а він стоїть на місці виразу, тобто перед for: [ціна if ціна < 100 else 0 for ціна in цінник].
Питання 8 / 8

У тебе включення на 75 символів із двома for, двома if і викликом round всередині. Воно працює правильно. Що з ним варто зробити?

Чому так. Включення — інструмент читабельності, і щойно воно перестає читатися вголос за один подих, воно втрачає весь сенс. Шість рухомих частин (два for, два if, виклик і розпакування) — це вже за межею. Аргумент про швидкість не рятує: включення виграє в циклу десятки відсотків, а не рази, і ця різниця майже ніколи не варта втраченої зрозумілості.