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

Списки й кортежі: контракт послідовності

Послідовність — це не просто «кілька значень». Вона має порядок, межі, правила зміни й очікувану форму елемента. Вибір між list і tuple має показувати, чи колекція росте й редагується, чи фіксує стабільний запис для читання та unpacking.

listtupleslicingunpacking

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

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

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

Спочатку визначте форму

Перед створенням collection запишіть: що означає один element, чи важливий order, чи дозволені duplicates, хто має право змінювати container і що робити з порожнім input. Без цього items швидко перетворюється на суміш рядків, чисел і випадкових sentinel values.

ElementОдин type або задокументована record shape.
OrderBusiness order, presentation order чи неважливий.
MutationХто додає, видаляє або замінює values.
EmptyВалідний результат, warning або contract violation.

list — змінна впорядкована послідовність

routes = ["standard", "urgent", "review"]
routes.append("archive")
first = routes[0]
last = routes[-1]
middle = routes[1:3]

Index читає одну позицію й піднімає IndexError поза межами. Slice використовує half-open interval: start входить, stop — ні; надто широка межа не падає, а повертає доступну частину. Це різні контракти, тому negative test для index і boundary test для slice мають бути окремими.

Методи, що змінюють list, повертають None

routes = ["review", "urgent", "standard"]
result = routes.sort()

print(routes)  # список відсортований
print(result)  # None

append, extend, sort і reverse змінюють object на місці та не повертають сам collection. Запис routes = routes.sort() втрачає binding до list. Якщо потрібен новий результат зі збереженням input, використайте sorted(routes).

tuple фіксує container, але не заморожує вкладені objects

record = ("case-17", "urgent", 75)
case_id, route, minutes = record

nested = (["review"], "owner-a")
nested[0].append("urgent")  # inner list mutable

Tuple не підтримує item assignment, але його елемент може бути mutable. Тому «tuple = усе immutable» — неправильна модель. Tuple доречний для невеликої стабільної структури, яку unpack-ять за позиціями; коли полів багато або їхній сенс неочевидний, потрібна виразніша record model у наступних модулях.

Copy — це рішення про ownership

original = [["a"], ["b"]]
shallow = original.copy()
shallow.append(["c"])
shallow[0].append("shared")

print(len(original))      # 2: outer list independent
print(original[0])        # ["a", "shared"]: inner list shared

Shallow copy створює новий outer container і повторно використовує references на вкладені objects. Не застосовуйте deepcopy автоматично: він може копіювати більше, ніж дозволяє domain ownership. Краще спростити shape або явно побудувати потрібні nested values.

Практика й Definition of Done

  1. Опишіть collection contract для synthetic queue records.
  2. Перевірте empty, first, last, exact slice та out-of-range index.
  3. Порівняйте sort() і sorted() з assertion про input.
  4. Розпакуйте tuple у names і навмисно перевірте wrong arity.
  5. Покажіть shallow-copy boundary на вкладеному list.
Done: shape, order і mutation policy названі; caller-owned input не змінюється без явного контракту; index/slice й copy behavior мають окремі tests.

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

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

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

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

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

1. Функція отримує впорядковані routes, дозволяє повтори й має додавати нові значення. Який collection найкраще відповідає контракту?
2. Для routes із трьох елементів code читає routes[3]. Який результат треба очікувати й перевіряти negative test-ом?
3. Які elements повертає routes[1:3] для list із позиціями 0, 1, 2, 3 і чому stop=3 не входить?