tuple и set: фиксированная запись и коллекция без повторов

Цели урока
  • Создавать tuple, обращаться к его элементам и распаковывать его в переменные (Unpacking)
  • Объяснить, почему tuple нельзя изменить и когда это преимущество
  • Создавать set, добавлять и удалять элементы и убирать повторы из списка
  • Выполнять операции над множествами — объединение, пересечение и разность

Что мы изучим?

Ещё две структуры данных, у каждой своя «суперсила»:

  • tuple (кортеж) — как список, но фиксированный: после создания его нельзя изменить.
  • set (множество) — коллекция без повторов и без порядка, которая позволяет очень быстро проверить, есть ли в ней значение.

Зачем это нужно?

  • tuple подходит для данных, которые представляют одну запись с фиксированной структурой: точка (x, y), дата (2026, 10, 6), строка из базы данных (7, "Dana", 24). В темах бэкенда и баз данных каждая строка, которая возвращается из базы данных, будет приходить как tuple! Неизменяемость гарантирует, что никакой код не изменит запись «по ошибке».
  • set подходит для случаев, когда нужна уникальность: сколько разных пользователей зашло сегодня на сайт? Какие теги у поста? Кто записан сразу на два курса?

Объяснение с основ

tuple

tuple — упорядоченная последовательность значений, которую нельзя изменить (Immutable). После создания нельзя добавлять, удалять или заменять элементы.

  • Записывается в круглых скобках: (1, 2, 3).
  • Доступ к элементам как у списка: point[0], point[-1], len(point), in.
  • Нет append, нет remove и нельзя присвоить значение элементу.

Распаковка (Unpacking): tuple можно «распаковать» прямо в переменные:

student = ("Dana", 24, "Haifa")
name, age, city = student

Мы уже пользовались этим незаметно: for name, age in attempts: и for position, name in enumerate(...).

Аналогия

list — как список покупок на доске: добавляешь, стираешь, меняешь. tuple — как дата рождения в удостоверении личности: напечатана один раз, и никто не должен её менять.

set

set — коллекция уникальных значений:

  • Без повторов — добавление уже существующего значения ничего не делает.
  • Без порядка — индексов нет. my_set[0] — ошибка. Порядок при печати может быть любым.
  • Изменяемый — можно добавлять и удалять.
  • Очень быстрая проверка in, даже при миллионе элементов. В списке in идёт элемент за элементом.
  • Записывается в фигурных скобках: {1, 2, 3}. Но пустое множество создают через set(), потому что {} — это пустой dict (следующий урок).

Операции над множествами

ОперацияОператорЗначение
Объединение (union)a | bВсё, что есть в a или в b
Пересечение (intersection)a & bТо, что есть и в a, и в b
Разность (difference)a - bТо, что есть в a и нет в b

Синтаксис

# tuple
point = (3, 5)
single = (7,)              # a tuple with ONE item needs a comma!
x, y = point               # unpacking
point[0]                   # 3

# set
tags = {"python", "web"}
empty_set = set()          # NOT {} - that is an empty dict
tags.add("api")            # add one item
tags.remove("web")         # remove (KeyError if missing)
tags.discard("xyz")        # remove if present, no error if missing
"python" in tags           # fast membership test
unique = set([1, 1, 2])    # {1, 2} - remove duplicates from a list

a | b    # union
a & b    # intersection
a - b    # difference

Первый пример кода

week-2/tuples_demo.py:

student = ("Dana", 24, "Haifa")

print("Full record:", student)
print("Name:", student[0])
print("Fields:", len(student))

name, age, city = student
print(name, "is", age, "and lives in", city)

student[1] = 25

Вывод:

Full record: ('Dana', 24, 'Haifa')
Name: Dana
Fields: 3
Dana is 24 and lives in Haifa
Traceback (most recent call last):
  File "tuples_demo.py", line 10, in <module>
    student[1] = 25
TypeError: 'tuple' object does not support item assignment

Разбор кода построчно

СтрокаОбъяснение
student = ("Dana", 24, "Haifa")tuple с 3 полями. Позиция задаёт смысл: 0 = имя, 1 = возраст, 2 = город.
student[0]Доступ как в списке.
name, age, city = studentРаспаковка: первый элемент идёт в name, второй — в age, третий — в city. Число переменных должно совпадать с числом элементов.
student[1] = 25Попытка изменить, и выбрасывается TypeError. Это не сбой, это защита, которую даёт tuple.

Хотите «изменить» tuple? Создайте новый: student = (student[0], 25, student[2]).

Ещё один пример

Анализ посетителей сайта с помощью set. week-2/visitors.py:

monday_visits = ["dana", "avi", "dana", "noa", "avi", "dana"]
tuesday_visits = ["noa", "yossi", "rina", "noa"]

monday = set(monday_visits)
tuesday = set(tuesday_visits)

print("Monday page views:", len(monday_visits))
print("Monday unique visitors:", len(monday), monday)

print("Visited on both days:", monday & tuesday)
print("Visited on any day:", monday | tuesday)
print("Only on Monday:", monday - tuesday)

tuesday.add("dana")
tuesday.add("noa")
print("Tuesday after adds:", len(tuesday), "unique")
print("Did yossi visit on Monday?", "yossi" in monday)

Вывод (порядок элементов внутри {} у вас может отличаться):

Monday page views: 6
Monday unique visitors: 3 {'avi', 'noa', 'dana'}
Visited on both days: {'noa'}
Visited on any day: {'dana', 'yossi', 'rina', 'avi', 'noa'}
Only on Monday: {'avi', 'dana'}
Tuesday after adds: 4 unique
Did yossi visit on Monday? False

Разбор:

  • set(monday_visits) — превращает список в множество, и повторы исчезают: 6 просмотров, 3 посетителя.
  • monday & tuesday — пересечение: только тот, кто есть в обоих (noa).
  • monday | tuesday — объединение: все, кто заходил, каждый по одному разу.
  • monday - tuesday — разность: заходили в понедельник и не заходили во вторник.
  • tuesday.add("noa") — noa уже есть, поэтому ничего не происходит. Добавилась только dana, и их стало 4 (noa, yossi, rina, dana).

Что когда использовать? Сравнительная таблица

listtupleset
Запись[1, 2](1, 2){1, 2}
Порядок / индекс✓✓✗
Можно изменять✓✗✓
Повторы✓✓✗
Типичное использованиеКоллекция, которая растёт и меняетсяЗапись с фиксированной структуройУникальность и проверка принадлежности

Типичная ошибка

Ошибка 1: tuple из одного элемента без запятой.

colors = ("red")
print(type(colors))
<class 'str'>

Одни скобки — просто арифметические скобки, как (2 + 3). Чтобы создать tuple из одного элемента: ("red",). tuple создаёт запятая, а не скобки.

Ошибка 2: {} как пустое множество.

seen = {}
seen.add("dana")
AttributeError: 'dict' object has no attribute 'add'

{} — пустой dict. Пустое множество = set().

Ошибка 3: ожидать порядок или индекс в set.

names = {"dana", "avi"}
print(names[0])
TypeError: 'set' object is not subscriptable

У set нет «первого». Если нужен порядок, превратите его в отсортированный список: sorted(names).

Ошибка 4: распаковка с несовпадающим числом переменных.

name, age = ("Dana", 24, "Haifa")
ValueError: too many values to unpack (expected 2)

Практика

Упражнения опираются только на то, что пройдено в этом уроке и в предыдущих. Сначала попробуйте сами, и только потом открывайте решение.

Упражнение 1: Распаковка

student = ("Dana", 24, "Haifa")

Распакуйте tuple в три переменные одной строкой и напечатайте о них предложение. Затем попробуйте изменить возраст на 25 — что произойдёт?

Ожидаемый вывод:

Dana is 24 and lives in Haifa
Показать решение
student = ("Dana", 24, "Haifa")

name, age, city = student
print(name, "is", age, "and lives in", city)
Dana is 24 and lives in Haifa

student[1] = 25 выбросит TypeError: 'tuple' object does not support item assignment — tuple неизменяем (Immutable). Если нужно его изменить, создайте новый tuple: student = (name, 25, city).

Упражнение 2: Функция, которая возвращает два значения

Напишите функцию min_max(numbers), которая возвращает tuple из наименьшего и наибольшего. Распакуйте результат в две переменные.

lowest, highest = min_max([40, 3, 99, 17])
print(lowest, highest)

Ожидаемый вывод:

3 99
Показать решение
def min_max(numbers):
    return (min(numbers), max(numbers))


lowest, highest = min_max([40, 3, 99, 17])
print(lowest, highest)
3 99

Функция всегда возвращает одно значение — здесь tuple. Распаковка на стороне вызывающего кода превращает его в две переменные.

Упражнение 3: Уникальные посетители

visits = ["dana", "avi", "dana", "noa", "avi", "dana"]

Напечатайте, сколько было просмотров, сколько было разных посетителей и заходил ли "tom".

Ожидаемый вывод:

6 views
3 visitors
False
Показать решение
visits = ["dana", "avi", "dana", "noa", "avi", "dana"]

unique = set(visits)
print(len(visits), "views")
print(len(unique), "visitors")
print("tom" in unique)
6 views
3 visitors
False

set не хранит повторов, поэтому len(set(...)) считает, сколько разных значений. Проверка in для множества к тому же очень быстрая.

Упражнение 4: Операции над множествами

football = {"dana", "avi", "noa", "tom"}
chess = {"noa", "rina", "tom", "yossi"}
  1. Кто состоит в обоих кружках?
  2. Кто только в футболе?
  3. Сколько всего разных детей?

Напечатайте ответы 1 и 2 отсортированными, чтобы порядок был фиксированным.

Ожидаемый вывод:

['noa', 'tom']
['avi', 'dana']
6
Показать решение
football = {"dana", "avi", "noa", "tom"}
chess = {"noa", "rina", "tom", "yossi"}

print(sorted(football & chess))
print(sorted(football - chess))
print(len(football | chess))
['noa', 'tom']
['avi', 'dana']
6
  • & — пересечение (в обоих). - — разность (только в первом). | — объединение (хотя бы в одном из них).
  • У множества нет фиксированного порядка, поэтому sorted возвращает отсортированный список для печати.

Упражнение 5: list, tuple или set?

Для каждого случая — какую структуру вы бы использовали? Объясните.

  1. Координаты точки на карте: широта и долгота.
  2. Список задач, в который вы добавляете и из которого удаляете, по порядку.
  3. Адреса электронной почты всех зарегистрировавшихся — без повторов.
  4. Очередь на кассе в супермаркете.
Показать решение
  1. tuple — фиксированная запись из двух значений, которые не должны меняться: (32.08, 34.78).
  2. list — порядок важен, и вы добавляете и удаляете.
  3. set — без повторов и с быстрой проверкой, есть ли уже такой адрес.
  4. list — порядок важен, и берут с начала (pop(0)).

Итоги

  • tuple ( , ) — упорядоченный, нельзя изменить. Подходит для записи с фиксированной структурой. Один элемент: (x,).
  • Распаковка: a, b = (1, 2). Так возвращают и получают несколько значений из функции.
  • set { } — без повторов, без порядка, без индекса. Пустое множество = set().
  • set(list) убирает повторы. in для множества очень быстрый.
  • Операции над множествами: | объединение, & пересечение, - разность.
  • В темах бэкенда и баз данных строки из базы данных будут возвращаться как tuple.

Официальная документация