Задачи на кортежи Python: практика с решениями
Пять задач на кортежи из практики: точки и функции, максимум с минимумом одним вызовом, защита записей от правок, ходы как ключи словаря и сортировка по полю. Код, вывод, разбор.
Редакция Питоники
Уроки про кортежи дали три права: неизменяемость из урока 11, сравнение со списком из урока 12, распаковка из урока 13. Пять задач ниже показывают эти права за работой: координаты в функциях, статистика одним вызовом, записи, которые не испортить, и ходы как ключи словаря. К каждой — код, честный вывод и разбор, почему кортеж здесь лучше списка.
Задача 1: координаты проходят через функции
Точка на плоскости — пара чисел, и кортеж для неё естественен: фиксированный состав, два значения, защита от случайной правки. Напишем сложение точек — функция принимает два кортежа и возвращает новый:
def add_points(a, b):
return (a[0] + b[0], a[1] + b[1])
p1 = (2, 3)
p2 = (5, 7)
p3 = add_points(p1, p2)
print(p1, '+', p2, '=', p3)
print(p3[0] - p1[0], p3[1] - p1[1])
(2, 3) + (5, 7) = (7, 10) 5 7
Кортеж приехал в функцию, из функции вышел кортеж — идиома возврата из урока 14. Печать кортежа целиком безопасна: (7, 10) стабилен, в отличие от множеств. Вторая печать — проверка: разность между суммой и первым слагаемым вернула второе слагаемое, сложение честное.
Задача 2: максимум и минимум сразу
Таблица результатов: имя и очки. Нужно найти рекордсмена и вывести таблицу по убыванию очков. Функция max с параметром key читает у каждой записи поле очков, а sorted с тем же key раскладывает записи:
results = [
('Анна', 12),
('Борис', 9),
('Вера', 15),
('Глеб', 9),
]
best = max(results, key=lambda r: r[1])
print('рекордсмен:', best)
print('имя:', best[0], '- очков:', best[1])
print()
for name, score in sorted(results, key=lambda r: r[1], reverse=True):
print(name, '-', score)
рекордсмен: ('Вера', 15)
имя: Вера - очков: 15
Вера - 15
Анна - 12
Борис - 9
Глеб - 9Обратите внимание на Бориса и Глеба: очки равные, и порядок между ними остался исходный. Сортировка Python стабильна — равные элементы сохраняют прежний порядок, и таблица предсказуема. Распаковка в заголовке цикла из урока 13 дала колонки name и score без индексов.
Задача 3: запись, которую не испортить
Половина ошибок в больших программах — случайные правки чужих данных: функция брала список пользователя и меняла его по ходу. Кортеж делает такую правку невозможной — не по договорённости, а на уровне языка:
record = ('Анна', 25, 'Москва')
try:
record[1] = 26
except TypeError as e:
print('TypeError:', e)
print('возраст по записи:', record[1])
TypeError: 'tuple' object does not support item assignment возраст по записи: 25
Кортеж не запрещает работать с данными — он запрещает портить их случайно: правка записи падает громко и сразу, а не портит отчёт. Возраст 25 пережил попытку. Если день рождения наступил — строится новая запись из старой: updated = (record[0], 26, record[2]), и старая остаётся нетронутой.
Задача 4: ходы как ключи словаря
В логе игры записаны ходы — пары координат сдвига. Задача: посчитать, какой ход делали чаще. Пара — ключ словаря, и тут кортеж незаменим: список ключом быть не может, потому что у него нет хеша из урока 17:
moves = [(0, 1), (1, 0), (0, 1), (0, 1), (1, 0), (1, 1)]
counts = {}
for m in moves:
counts[m] = counts.get(m, 0) + 1
print('разных ходов:', len(counts))
for move, n in sorted(counts.items()):
print(move, '-', n)
разных ходов: 3 (0, 1) - 3 (1, 0) - 2 (1, 1) - 1
Шесть ходов свелись к трём разным: ключи-кортежи сами отфильтровали повторы, get с нулём по умолчанию завёл счётчик с первого вхождения. Печать items() через sorted дала порядок по ключам: (0, 1) меньше (1, 0), потому что сравнение кортежей идёт поэлементно. Тот же приём — подсчёт частот — встретился в задачах на множества, только там ключами были имена, здесь — пары.
Задача 5: кортеж из одного элемента
Задача на чтение чужого кода, и в ней чаще всего ошибаются: чем отличается (5) от (5,)? Ответ — всем: скобки создают не кортеж, кортеж делает запятая:
not_tuple = (5)
is_tuple = (5,)
print(type(not_tuple).__name__, type(is_tuple).__name__)
print(len(is_tuple))
print(type((1, 2)).__name__)
int tuple 1 tuple
(5) — число в скобках, как в школьной арифметике: приоритет вычислений. (5,) — кортеж из одного элемента, и len подтверждает. Отсюда привычка: единственный элемент кортежа в данных или параметрах пишите с хвостовой запятой — она не мешает и при расширении записи до двух полей.
point = (1, 2)
extended = point + (3,)
print(point)
print(extended)
(1, 2) (1, 2, 3)
Исходная точка не изменилась — кортеж не умеет меняться, и сложение вернуло новый объект. Правило то же, что у строк: любые «изменения» — это новые значения, старые остаются при своих данных.
rows = ([],) * 3
rows[0].append('X')
print(rows)
(['X'], ['X'], ['X'])
| Задача | Инструмент | Что даёт кортеж |
|---|---|---|
| Точки и векторы | Функция с кортежами | Фиксированный состав, возврат пары |
| Максимум по полю | max(key=lambda r: r[1]) | Запись целиком, не только число |
| Защита записи | Неизменяемость | Правка падает вместо порчи данных |
| Счётчик ходов | Кортеж-ключ словаря | Пары как уникальные ключи |
| Один элемент | (5,) с запятой | Запятая делает кортеж, скобки нет |
Что дальше
Пять задач закрыли повседневную жизнь кортежей: передача через функции, максимум по полю, защита записей, ключи словаря, единичный элемент. Остался последний шаг раздела — проект по анализу посетителей: журнал визитов, где множества отвечают за уникальность и пересечения, а кортежи — за возвраты из функций и ключи. Читайте namedtuple, если записи захотят имён полей.
Кортеж в задачах — два в одном: данные и замок. Пара координат или запись проходит через функции без риска быть изменённой по дороге, а хеш делает её ключом словаря — списку такое недоступно.
Сначала предскажи ответ в голове — это главный навык программиста.
t = (7,)
print(len(t), type(t).__name__)
print(t * 2)
pairs = [(1, 'b'), (2, 'a'), (3, 'b')]
print(sorted(pairs, key=lambda p: p[1])[0])
x, y = (10, 20)
point = (y, x)
print(point)
1. Функция add_points принимает два кортежа и возвращает сумму. Что она вернёт?
2. Как найти запись с максимальными очками в списке кортежей (имя, очки)?
3. Борис и Глеб набрали поровну очков. В каком порядке они окажутся после sorted по очкам?
4. record[1] = 26 у кортежа упадёт. Что говорит эта ошибка?
5. Почему ходы (0, 1) годятся в ключи словаря, а списки [0, 1] — нет?
6. Чем (5) отличается от (5,)?
7. Как «добавить» элемент к кортежу point = (1, 2)?
Даны два кортежа координат a = (2, 3) и b = (4, 6). Напишите функцию midpoint, возвращающую кортеж со средними координатами (по каждой оси — среднее двух чисел), и напечатайте её результат.
Как передать в функцию и вернуть из неё пару значений-координат?
Кортежем: def add_points(a, b): return (a[0] + b[0], a[1] + b[1]). Кортеж на входе защищает координаты от правок, кортеж на выходе — идиома возврата нескольких значений из урока 14.
Урок 14: функция возвращает несколько значенийКак найти максимум в списке кортежей по одному полю?
max(items, key=lambda item: item[1]) — параметр key говорит, по какому элементу сравнивать, и возвращает запись целиком. Для сортировки по полю — sorted(items, key=lambda item: item[1]); сортировка стабильна, равные сохраняют исходный порядок.
Зачем хранить записи кортежами, если список умеет всё то же?
Ради защиты: кортеж нельзя изменить ни случайно, ни по чужой ошибке — правка падает сразу. Список молча допускает append и присваивание, и испорченная запись проявится далеко от места ошибки. Кортеж плюс хеш делает запись ещё и ключом словаря.
Урок 12: кортеж против спискаКак посчитать, сколько раз встречалась каждая пара значений?
Словарём с ключами-кортежами: counts[pair] = counts.get(pair, 0) + 1. Кортеж хешируем, поэтому годится в ключ; список — нет. Печать через sorted(counts.items()) даёт порядок по ключам: кортежи сравниваются поэлементно.
Почему (5) не кортеж?
Кортеж создаёт запятая, а не скобки: (5) — это число 5 в скобках приоритета, type покажет int. Кортеж из одного элемента пишется (5,) — запятая обязательна и не мешает при расширении записи.
Понравился урок? Сошлитесь на него
«Кортеж не запрещает работать с данными — он запрещает портить их случайно: правка записи падает громко и сразу, а не портит отчёт.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Множества · Урок 11
Tuple в Python: неизменяемый кортеж и доступ по индексу
Кортеж хранит фиксированный набор значений и защищает его от изменений: создали — и состав застыл. Создание, доступ по индексу, IndexError и то, почему запятая главнее скобок.
Множества · Урок 13
Распаковка кортежей в Python: x, y = point
Один кортеж — несколько переменных за один шаг: x, y = point. Классический обмен значений, звёздочка для остатка и почему распаковывать множества опасно.
Множества · Урок 20
Проект: анализ уникальных посетителей на Python
Итоговый проект: журнал из 12 визитов вида «имя:день» превращается в отчёт — уникальные посетители, гости по дням, постоянные через пересечение, топ повторов. Три куска, каждый самодостаточен.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
NumPy · Урок 10
Проект на NumPy: анализируем температуру за год и строим отчёт
Финальный проект раздела: генерируем год температуры с фиксированным seed, считаем статистику по месяцам через reshape(12, 30), ловим аномалии масками, сглаживаем ряд и печатаем отчёт.
numpy проект для начинающихnumpy задачи с решениями
json · Урок 20
Проект: каталог книг — от URL до файла
Финал раздела: один скрипт собирает каталог книг — параметры в URL, разбор ответа, фильтр по рейтингу, сортировка по цене и проверенный файл на диске.
python проект пример для начинающихpython практика json фильтр сортировка
Множества · Урок 12
Кортеж против списка в Python: что и когда использовать
У обоих есть индексы, len и in, но список можно менять, а кортеж — нет. Четыре отличия: изменяемость, ключ словаря, память и правило выбора за три секунды.
python кортеж против спискакортеж или список python