Как используется кортеж в Python как структура с фиксированным количеством и типами данных на каждой позиции?
Что проверяют
Понимаете ли вы кортеж как запись, где позиция задаёт смысл и тип, а не как «неизменяемый список». Следом почти всегда спрашивают, чем такой кортеж хуже NamedTuple или dataclass и как описать его в аннотациях типов.
Как отвечать
Начните с ролей. Список это однородная коллекция переменной длины, а кортеж часто работает лёгкой структурой: в ("Анна", 30, True) первая позиция имя, вторая возраст, третья флаг, и переставлять их нельзя.
- аннотации: с Python 3.9 пишут
tuple[str, int, bool], это фиксированная длина и свой тип на каждой позиции. Однородный кортеж любой длины записывается какtuple[int, ...]. mypy и pyright знают, чтоrow[1]имеет типint, и ругаются на лишний элемент; - распаковка:
name, age, active = rowчитается лучше индексов, для хвоста естьfirst, *rest = row, аmatch row: case (name, age, _):разбирает структуру по шаблону; - несколько значений из функции:
return user, createdна самом деле возвращает один кортеж; - ключи словарей: кортеж хешируем, если хешируемы все его элементы, поэтому
(lat, lon)подходит в ключ; NamedTuple: даёт доступ по имени,point.x, и при этом остаётся кортежем с распаковкой. Когда полей много или нужны методы и значения по умолчанию, берут@dataclass(frozen=True, slots=True).
Упомяните синтаксис: кортеж создаёт запятая, а не скобки. Одиночный элемент пишется (1,), а (1) это просто число.
Где спотыкаются
Говорят, что кортеж полностью неизменяем. Неизменяем набор ссылок: список внутри (1, [2, 3]) меняется спокойно, а попытка сделать такой кортеж ключом словаря падает с TypeError: unhashable type: 'list'.
Путают tuple[int] и tuple[int, ...]. Первое означает ровно один элемент, и проверка типов отклонит (1, 2).
Строят на голых кортежах из пяти полей всю модель данных. Через месяц никто не помнит, что лежит в row[3]. Это аргумент за NamedTuple или dataclass, и он про читаемость, а не про скорость: выигрыш кортежа по памяти и времени небольшой.