logo
Ещё

Кортежи в Python

Кортеж – тип данных, с которым вы будете сталкиваться регулярно: в словарях, в возвращаемых значениях функций, при работе с JSON и так далее. Кортежи во многом похожи на списки, но свои особенности у этого типа данных тоже есть – если вы не будете знать этих особенностей, то можете получить посреди кода ошибку, которую будет трудно отловить. Ниже – все о кортежах: что это, как их создавать и как ими манипулировать.

Кортежи в Python – что это?

Зайдем немного издалека: почти любое приложение – это алгоритм, что-то делающий с данными, и эти данные нам нужно где-то хранить (примечание: исключением являются stateless-приложения, но они встречаются крайне редко). Простое и понятное место для хранения – переменные, с ними в Python все просто: кладем любое значение в переменную, достаем при необходимости.

Но переменные – не всегда удобно: если у вас есть имя, возраст и пол пользователя, вам бы хотелось хранить их в одном месте; 20 случайно сгенерированных чисел, необходимых вам для каких-то целей, тоже лучше было бы хранить в одной переменной, а не в 20 разных. Для таких задач есть структуры данных – некоторое выраженное командами языка соглашение, которое позволяет хранить в одном месте несколько единиц информации. Для многих ЯП самой базовой структурой языка является массив: четко ограниченная по вместимости последовательность данных одного типа. Например: [1,2,3,4,5] – массив целых чисел, хранящий до 5 элементов.

В Python базовая структура данных – список: изменяемая упорядоченная последовательность произвольной ширины, которая позволяет хранить любые элементы. Проще говоря: кладем что угодно в какой угодно последовательности, при необходимости обращаемся к элементу в конкретной позиции, если надо – добавляем/изменяем/удаляем элемент. Кортеж – это неизменяемая упорядоченная последовательность, которая позволяет хранить любые элементы. В чем разница:

  • Изменяемость. Списки изменяемы, кортежи – неизменяемы. В кортеж нельзя добавить новый элемент, из кортежа нельзя удалить элемент, элемент кортежа нельзя изменить (за одним исключением – смотрите FAQ).
  • Упорядоченность. И списки, и кортежи позволяют обращаться к их элементам по индексу: example_tuple[0] вернет вам первый элемент кортежа.
  • Ширина. Списки могут быть произвольной ширины (в том числе и пустыми). Вы можете создать кортеж любой ширины, но поскольку кортеж – неизменяемый, характеристика «произвольная ширина» не имеет для него особого смысла.
  • Тип элементов. И в кортеже, и в списке можно хранить любые элементы.

Основное преимущество кортежей перед списками – кортежи и едят меньше памяти, и работают быстрее (более детально можно почитать здесь) за счет неизменяемости. Она же и составляет основной недостаток кортежа – если вам нужно хранить динамично меняющиеся данные, кортеж не подойдет. Вы будете часто встречать кортежи в возвращаемых значениях функций – Python позволяет вернуть из функции только одно значение, поэтому если нужно вернуть несколько, их обычно оборачивают в кортеж или словарь. Более редкое, но все еще важное применение – кортежи могут являться ключами списков, потому что они неизменяемы.

Как они создаются и что с ними можно делать?

Самый простой способ создания кортежа – перечислением его элементов через запятую:

test_tuple = 1, 2, 3, 'a', 'b', 'c'

Элементы можно взять в скобки для наглядности, но это – не обязательно. Основной кейс, когда скобки обязательны – если мы помещаем кортеж в другой кортеж:

test_tuple = ((1, 2, 3), ('a', 'b', 'c'))

Второй случай, когда скобки обязательны – если мы создаем пустой кортеж:

test_tuple = ()

Если создаете кортеж с одним элементом – после элемента нужно поставить запятую, иначе интерпретатор присвоит переменной тип элемента:

test_tuple = 70,

Второй способ создания – с помощью встроенной функции tuple(). Она способна принимать на вход практически любые значения и формировать из них кортеж. Особенно она полезна тем, что в нее можно передать любой итерируемый объект, и он будет преобразован в кортеж:


Здесь же кроется и проблема – если вам нужно засунуть, например, строку в кортеж, вы не можете просто отдать ее функции tuple() – функция нарежет строку на символы. Придется выкручиваться, самый простой способ – создать пустой кортеж, после чего через «+» присоединить к нему кортеж со строкой:


С кортежами можно делать все то же самое, что и со списками (кроме модификации элементов):

  • Доступ по индексу. print(test_tuple[3]). Индексация начинается с нуля. Как и в случае со списками – для вложенных итерируемых элементов можно пользоваться вложенной индексацией, print(test_tuple[1][2]).
  • Сравнение. print(tuple1 == tuple2). Если кортежи имеют одну и ту же длину и одни и те же элементы на одинаковых индексах – они равны. Кроме того, кортежи поддерживают «больше» и «меньше», но пользоваться таким сравнением – плохая практика из-за запутанности правил сравнения.
  • Проверка принадлежности. print('a' in test_tuple). Если элемент есть – возвращает True, иначе возвращает False.
  • Конкатенация и повторение. print(tuple1 + tuple2). print(tuple1 * 5). Работает ровно так же, как и со строками.
  • Удаление. del test_tuple. Можно удалить только весь кортеж.
  • Перебор. for elem in test_tuple:. Работает так же, как и с другими итерируемыми объектами.

Отдельно стоит упомянуть про упаковку и распаковку. С упаковкой мы уже познакомились – для того, чтобы упаковать значения в кортеж, вам нужно просто объединить их через запятую. Распаковка же – это когда мы распаковываем кортеж на отдельные переменные. Например, если у нас есть кортеж из 3 чисел, то распаковать его можно так:


Иногда случается так, что нам нужно распаковать не весь кортеж, а только часть его – в этом случае нужно использовать переменную, перед которой стоит «*», все нераспакованные переменные пойдут в нее. Эта переменная может стоять в начале, середине или конце распаковки, в выражении распаковки можно использовать только одну «*». Пример:


Обратите внимание, что переменная middle содержит список, а не кортеж.

Функции для кортежей

Как и для многих вещей в Python, для кортежей в языке есть ряд встроенных функций, вот они:

  • Количество элементов. len(test_tuple). Возвращает количество элементов в кортеже.
  • Сумма элементов. sum(test_tuple). Возвращает сумму элементов.
  • Минимальный или максимальный элемент. min(test_tuple). max(test_tuple). Возвращает минимальный/максимальный элемент кортежа.

  • Сортировка. test_tuple = tuple(sorted(test_tuple[, reverse=True])). Сортирует кортеж по возрастанию. Поскольку кортеж – неизменяемая структура данных, и sorted() возвращает список, нам нужно присвоить в какую-либо переменную результат сортировки, и этот результат нужно сконвертировать из списка в кортеж. Если нужно отсортировать кортеж по убыванию – используем необязательный флаг reverse.

  • Срезы. sliced_tuple = test_tuple[2:5]. Работает так же, как и со строками.
  • Преобразование в другой тип данных. list_from_tuple = list(test_tuple). если хотите преобразовать кортеж в словарь – в каждом элементе кортежа должны находиться пары «ключ-значение».

FAQ – если нет времени читать

Что такое «кортеж»?

Кортеж – это неизменяемая упорядоченная структура данных, в которой можно хранить элементы разных типов. Кортежи работают быстрее, чем списки. Часто их используют для передачи результата работы функции.

Как их создавать?

Можно просто перечислить элементы через запятую – они объединятся в кортеж (упаковка кортежа). Можно передать в функцию tuple() итерируемый объект – на его основе будет создан кортеж.

Где можно почитать про кортежи?

Официальная документация: 5. Data Structures — Python 3.13.3 documentation.

В каких случаях можно изменять содержимое элемента кортежа?

Когда вы, например, создаете кортеж и помещаете в него списки – вы на самом деле помещаете в него не сами списки, а ссылки на них. Ссылку вы изменить не можете, а вот список по ссылке – вполне себе можете, то есть код

list1 = [1,2,3]

list2 = [4,5,6]

test_tuple = list1, list2

test_tuple[0][0] = 5

print(test_tuple[0])

будет работать, на выходе вы получите [5, 2, 3].