Кортежи в Python: зачем нужны неизменяемые последовательности
Этот урок переведён с английского оригинала.Read in EnglishLeer en españolСообщить об ошибке в переводе
Вспомните GPS-координаты. Точка (40.7128, -74.0060) обозначает Нью-Йорк. Если случайно изменить одно из этих чисел, точка окажется совсем в другом месте. Некоторые данные не должны меняться после того, как вы их создали.
С датами то же самое. 1 января 2025 года остаётся неизменным фактом. Вам вряд ли захочется, чтобы код случайно превратил эту дату в 37 февраля. Когда данные должны оставаться неизменными, Python предлагает кортежи.
Кортеж выглядит почти так же, как список, но с одним важнейшим отличием: созданный кортеж нельзя изменить. Нельзя добавить элемент, удалить его или заменить. В этом уроке вы узнаете, почему это ограничение на самом деле оказывается суперсилой.
Как создать кортеж в Python
Кортеж создают, перечисляя элементы через запятую внутри круглых скобок (). Можно создать кортеж и без скобок: кортежем его делают именно запятые.
(40.7128, -74.006)
('red', 'green', 'blue')
(42,)
<class 'tuple'><class 'int'> <class 'tuple'> () 0
Другие последовательности тоже можно превратить в кортеж с помощью конструктора tuple(). Это удобно, когда у вас есть список и его нужно «заморозить», чтобы никто не мог его изменить.
('apple', 'banana', 'cherry')
('h', 'e', 'l', 'l', 'o')Доступ к элементам кортежа и срезы
Доступ к элементам кортежа устроен точно так же, как у списков. Индекс указывается в квадратных скобках. Положительные индексы отсчитываются с начала, отрицательные с конца.
Jan Apr Jun May 6
Срезы работают так же. Часть кортежа можно получить с помощью tuple[start:end]. Результатом будет новый кортеж.
('Feb', 'Mar', 'Apr')
('Jan', 'Feb', 'Mar')
('May', 'Jun')
('Jan', 'Mar', 'May')А вот здесь кортежи отличаются от списков. Если попытаться изменить элемент, Python выбросит TypeError. Кортежи неизменяемые: после создания их нельзя изменить.
red
Упаковка и распаковка кортежей
Упаковка происходит, когда вы создаёте кортеж, присваивая одной переменной несколько значений. Распаковка работает наоборот: значения извлекаются из кортежа в отдельные переменные. Распаковка относится к самым полезным возможностям Python.
('Alice', 25, 'Engineer')
Alice
25
EngineerКоличество переменных слева должно совпадать с количеством элементов кортежа. Если они не совпадают, Python выбрасывает ValueError.
Классический пример распаковки: обмен значений двух переменных без временной переменной. В большинстве других языков для этого нужны три строки, а Python справляется в одну.
Before: a=10, b=20 After: a=20, b=10
При распаковке можно поставить звёздочку *, чтобы собрать оставшиеся элементы. Это называется расширенной распаковкой, и в результате вы получаете список из оставшихся элементов.
95 [87, 72, 68] 91
Alice scored 95 Bob scored 87 Charlie scored 72
Кортежи и списки: когда что использовать
Если кортежи всего лишь списки, которые нельзя менять, зачем они вообще нужны? Есть три веские причины: безопасность, производительность и ясность.
Безопасность: когда данные не должны меняться, кортеж защищает их от случайных изменений. GPS-координаты, цвета RGB, записи из базы данных относятся к неизменным фактам. Кортеж ясно показывает ваше намерение.
Производительность: кортежи немного быстрее списков и занимают меньше памяти. Для маленьких коллекций это почти незаметно, но на миллионах записей разница накапливается.
Ключи словаря: кортежи можно использовать как ключи словаря, потому что они неизменяемы. Списки так использовать нельзя. Это станет важно, когда вы начнёте изучать словари.
# Data that changes over time
shopping = ['milk', 'eggs']
shopping.append('bread')
# Collections you sort or filter
scores = [85, 92, 78]
scores.sort()# Fixed data that shouldn't change
coords = (40.7128, -74.0060)
rgb_red = (255, 0, 0)
# Returning multiple values
def get_name_age():
return 'Alice', 25Под капотом: почему кортежи быстрее списков
Поскольку кортежи неизменяемы, Python может незаметно применять к ним оптимизации. Размер кортежа фиксируется при создании, поэтому Python не нужно выделять лишнюю память на возможный рост, как он делает это для списков.
List size: 52 bytes Tuple size: 40 bytes
Кортежи поддерживают и все операции, которые не изменяют последовательность. count() считает, сколько раз встречается значение, index() находит позицию значения, in проверяет, есть ли элемент в кортеже, а + склеивает кортежи.
3 2 True (1, 2, 3, 4)
Практические упражнения
Пора попрактиковаться! Эти упражнения посвящены созданию кортежей, распаковке и пониманию неизменяемости.
Создайте кортеж seasons из четырёх времён года в виде строк: 'Spring', 'Summer', 'Fall', 'Winter'.
Затем выведите первое и последнее время года, каждое на отдельной строке.
Ожидаемый вывод:
Spring
WinterВнимательно прочитайте этот код. Что он выведет? Подумайте, что делает значение кортежем, а что оставляет его обычным числом в скобках.
Впишите вывод в точности.
Дан кортеж с данными об ученике. Распакуйте его в три переменные: name, age и grade.
Затем выведите каждую переменную на отдельной строке.
Ожидаемый вывод:
Emma
16
AЭтот код пытается заменить цвет в кортеже, но кортежи неизменяемы. Исправьте его так, чтобы программа выводила обновлённые цвета, не изменяя исходный кортеж. Вместо этого создайте новый кортеж.
Ожидаемый вывод:
('red', 'yellow', 'blue')Есть список кортежей, в каждом кортеже имя ученика и его балл. Переберите список, распакуйте каждый кортеж и выведите результат каждого ученика в таком формате:
Alice: 92
Bob: 85
Charlie: 78Итоги: что вы узнали о кортежах в Python
Повторим всё, что вы теперь знаете о кортежах:
| Понятие | Что делает | Пример |
|---|---|---|
| Создание кортежа | Хранит неизменный набор элементов | point = (3, 4) |
| Запятая в конце | Создаёт кортеж из одного элемента | solo = (42,) |
| Индексы | Доступ по позиции | point[0], point[-1] |
| Срезы | Получение части | months[1:4] |
| Распаковка | Извлечение в переменные | x, y = point |
| Расширенная распаковка | Собирает оставшиеся элементы через * | first, *rest = items |
count() | Считает вхождения | t.count(2) |
index() | Находит позицию | t.index(3) |
| Неизменяемость | Нельзя изменить после создания | Выбрасывает TypeError |
Кортежи идеально подходят для неизменных наборов данных: координат, цветов, записей и значений, которые возвращают функции. Благодаря неизменяемости код становится надёжнее, а ваши намерения понятнее.
Что дальше?
В следующем уроке, [Словари в Python](/python/python-dictionaries), вы научитесь хранить данные в виде пар «ключ: значение». Вместо доступа к элементам по позиции вы будете обращаться к ним по имени.
Словари относятся к самым мощным структурам данных в Python. Вместе со списками и кортежами они позволяют описать почти любые данные из реальной жизни.