Модуль 4 · Урок 16 із 58

Comprehensions і вибір структури даних

Comprehension стисло створює нову collection із iterable. Вона корисна, коли transform і filter залишаються очевидними. Якщо в одному виразі з’являються кілька business branches, side effects або незрозуміла nested shape, звичайний loop із named steps буде професійнішим.

comprehensionpipelinenested datanon-mutation

Безпечна практика модуля 4

Пакет містить тільки synthetic records, pure collection functions, import-safe CLI і локальні tests. Жодних персональних чи production-даних, secrets, мережевих викликів або зовнішніх залежностей.

Завантажити практичний пакет →

Один expression, один transform, один зрозумілий filter

minutes = [15, 60, -1, 75]
valid_minutes = [value for value in minutes if value >= 0]
labels = ["urgent" if value >= 60 else "standard" for value in valid_minutes]

List comprehension створює новий list і не має мутувати source. Condition після for фільтрує; conditional expression перед for обирає output value. Їх не можна міняти місцями без зміни сенсу.

Set і dict comprehensions мають collision semantics

normalized_tags = {tag.strip().lower() for tag in raw_tags if tag.strip()}

by_id = {record["id"]: record for record in records}

Set comprehension свідомо прибирає duplicates. Dict comprehension може тихо overwrite попередній record з тим самим key. Для identifiers спершу знайдіть duplicates, а вже потім будуйте index; красивий однорядковий вираз не виправдовує втрату evidence.

Nested records: validate, normalize, transform

def normalize_record(record: dict[str, object]) -> dict[str, object]:
    case_id = str(record["id"]).strip()
    tags = sorted({str(tag).strip().lower() for tag in record.get("tags", []) if str(tag).strip()})
    return {**record, "id": case_id, "tags": tags}

normalized = [normalize_record(record) for record in records]

Функція повертає новий outer dict, але spread є shallow copy: інші nested values можуть лишитися shared. Контракт має сказати, які fields перебудовані й які references збережені. Недовірений external payload не можна просто cast-ити без schema validation.

Як обрати collection

ПотрібноСтартовий вибірПеревірити
Порядок, повтори, позиціїlistMutation та boundary indices
Фіксована positional shapetupleArity й mutable nested items
Key → valuedictHashable unique keys і collision policy
Унікальність/membershipsetВтрату order та frequency

Не обирайте structure лише через «швидше». Спочатку correctness contract, розмір і pattern operations; performance твердження перевіряйте вимірюванням на репрезентативних synthetic data.

Коли повернутися до loop

normalized = []
rejected = []

for record in records:
    if "id" not in record:
        rejected.append({"reason": "missing_id", "record": record})
        continue
    normalized.append(normalize_record(record))

Loop кращий, коли потрібні multiple outputs, reason codes, logging, metrics або кілька guard clauses. Side effect усередині comprehension приховує порядок і ускладнює тест.

Практичний pipeline

  1. Візьміть synthetic records із лабораторії.
  2. Не змінюючи input, нормалізуйте ID й tags.
  3. Знайдіть duplicate IDs до побудови dict index.
  4. Побудуйте deterministic report із sorted tags і routes.
  5. Перевірте empty, duplicate, missing field, nested alias і stable output.
Definition of Done
  • Кожна collection має пояснений contract.
  • Comprehension лишається читабельною й без side effects.
  • Duplicate/collision evidence не губиться.
  • Input mutation перевірена snapshot assertion.
  • Output deterministic для однакового synthetic input.

Модуль 4 завершено

Після тесту прогрес становитиме 16/58 уроків і відкриється review-проєкт 1 «CLI utility». Фінальний іспит, PDF, QR та email-сертифікат лишаються заблокованими до всіх 58 уроків і чотирьох прийнятих проєктів.

Методичні джерела

Урок, сценарії, пояснення й вправи створені SEOWORK. Посилання ведуть лише на офіційну документацію Python.

Практична перевірка · урок 16 з 47

Закріпіть матеріал уроку

Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.

1. Що створює comprehension [value for value in minutes if value >= 0] і чи змінює він source list?
2. У виразі ['urgent' if m >= 60 else 'standard' for m in values] де працює conditional expression?
3. Dict comprehension {r['id']: r for r in records} отримав duplicate IDs. Який ризик приховує короткий syntax?