Код
#статьи

Что такое кортежи в Python и как их использовать

База «змееуста»: работаем с индексами, сравниваем и перебираем элементы.

Фото: Justin Sullivan / Getty Images

Что такое кортежи

Кортежи (тип tuple) — это неизменяемый тип данных в Python, который используется для хранения упорядоченной последовательности элементов.

У этих коллекций есть три замечательных свойства:

Неизменяемость. После того как кортеж создан, в него нельзя добавлять элементы, а также изменять их или удалять. При попытке это сделать интерпретатор выдаст ошибку TypeError.

Упорядоченность. Элементы кортежа располагаются в определённом порядке, который тоже неизменяем. К любому элементу можно обратиться по его индексу (порядковому номеру).

Элементами кортежа могут быть объекты разных типов данных: числа, строки, списки, другие кортежи и другие. Элементы-коллекции могут иметь неограниченную глубину вложенности. Например, кортеж может включать в себя список, который будет содержать другой список, который вновь будет содержать список и так далее.

Кортежи записываются с использованием круглых скобок ():

my_tuple = (значение1, значение2...)

my_tuple — имя переменной, которой присваивается кортеж.

(значение1, значение2...) — это сам кортеж, который содержит элементы значение1, значение2 и так далее.

Они могут состоять из элементов разных типов и их сочетаний:

# Кортеж из чисел, в том числе с плавающей точкой и комплексных
numbers_tuple = (1, 2, 3, 4, 5, 2.5, 3 + 4j)


# Кортеж из строк
fruits_tuple = ('яблоко', 'банан', 'апельсин')


# Кортеж из логических значений
my_tuple = (True, False)


# Кортеж из других кортежей
nested_tuple = ((1, 2), ('a', 'b'))


# Кортеж из списков
my_tuple = ([1, 2, 3], ['a', 'b', 'c'])


# Кортеж из словарей
my_tuple = ({'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25})


# Кортеж из разных типов данных
mixed_tuple = (1, 'hello', [1, 2, 3], {'a': 10})

Когда использовать кортеж

Применение кортежей связано с их свойствами — неизменяемостью и строгим порядком элементов. Разберём ситуации, когда это полезно.

Требуется защитить элементы от изменений

Если нужно защитить данные от случайного или намеренного изменения, то можно использовать кортежи. Например, этот тип данных подойдёт для сохранения информации о датах рождения клиентов.

Обратите внимание: неизменяемость кортежей не абсолютна. У неё есть исключение — если внутри кортежа находятся изменяемые элементы, например списки, словари или множества, то их значения можно изменить.

Например:

# Кортеж с изменяемыми элементами:
mutable_tuple = ([1, 2, 3], [4, 5, 6])


print('Исходный кортеж:', mutable_tuple)


# Изменение содержимого списка внутри кортежа
mutable_tuple[0][1] = 10 # Меняем второй элемент в первом списке
mutable_tuple[1].append(7) # Добавляем ко второму списку новое значение


print('Изменённый кортеж:', mutable_tuple)

Результат выполнения кода:

Исходный кортеж: ([1, 10, 3], [4, 5, 6])
Изменённый кортеж: ([1, 10, 3], [4, 5, 6, 7])

Как видите, никакой ошибки нет, хотя кортеж изменился.

Необходимо экономить память

Кортежи занимают в памяти меньше места, чем списки. Это легко проверить:

a = (10, 20, 30, 40, 50, 60) # Кортеж
b = [10, 20, 30, 40, 50, 60] # Список


print(a.__sizeof__()) # Размер кортежа
print(b.__sizeof__()) # Размер списка

В результате выполнения кода получим:

72
88

Кортеж занимает в памяти на 16 байт меньше, чем список. Из-за малой величины сравниваемых объектов разница почти незаметна, но при работе с данными большего объёма экономия может быть значимой.

Предстоит работать со словарями

Кортежи идеально подходят для использования в качестве ключей в словарях, так как ключи в них должны быть объектами неизменяемого типа данных. Проверим это:

# Создаём словарь с кортежем в качестве ключа
my_dict = {('a', 1): 'value1', ('b', 2): 'value2'}


# Обращаемся к элементам словаря по кортежу в качестве ключа
print(my_dict[('a', 1)])  # Вывод: value1
print(my_dict[('b', 2)])  # Вывод: value2


# Добавляем новый элемент с кортежем в качестве ключа
my_dict[('c', 3)] = 'value3'


# Выводим содержимое словаря
print(my_dict)

В результате получим:

value1
value2
{('a', 1): 'value1', ('b', 2): 'value2', ('c', 3): 'value3'}

С кортежем словарь работает. Если попытаться в качестве ключа использовать список, то возникнет ошибка, так как списки — изменяемый тип данных.

Как работать с кортежами в Python

Рассмотрим основные операции с кортежами.

Создание кортежа

Создать кортеж в Python можно по меньшей мере пятью способами. Рассмотрим каждый из них.

  • С помощью круглых скобок:
my_tuple = (1, 2, 3, 'a', 'b', 'c')
  • Без круглых скобок:
my_tuple = 1, 2, 3, 'a', 'b', 'c'
  • Используя встроенную функцию tuple():
my_tuple = tuple([1, 2, 3, 'a', 'b', 'c'])
  • С помощью оператора упаковки, который мы разберём дальше:
a = 1
b = 2
c = 3
my_tuple = a, b, c  # Эквивалентно (a, b, c)
  • Из итерируемого элемента, например строки, с помощью функции tuple():
my_tuple = tuple('hello')
# Результат: ('h', 'e', 'l', 'l', 'o')

Можно создать пустой кортеж:

empty_tuple = ()

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

single_element_tuple = (42,)
# Или так
single_element_tuple = 42,


# Если запятую не поставить, то получим объект типа int
single_element_tuple = (42)

Доступ к элементам по индексам

Кортеж — это упорядоченная последовательность. Поэтому для доступа к его элементам можно использовать индексы.

Индексация начинается с нуля и заканчивается значением, равным длине кортежа, уменьшенным на единицу:

# Кортеж из шести элементов
my_tuple = (1, 2, 3, 'a', 'b', 'c')


# Доступ к элементам по индексу
first_element = my_tuple[0] # Первый элемент
second_element = my_tuple[1] # Второй элемент
third_element = my_tuple[2] # Третий элемент
last_element = my_tuple[5] # Последний элемент


# Вывод значений
print(first_element)  # Вывод: 1
print(second_element) # Вывод: 2
print(third_element)  # Вывод: 3
print(last_element)  # Вывод: 'c'

Для доступа к элементам с конца кортежа можно использовать отрицательные индексы. В этом случае индексация начинается с -1 и заканчивается значением, равным длине кортежа со знаком минус.

Напишем код:

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


last_element = my_tuple[-1] # Первый элемент с конца
second_to_last_element = my_tuple[-2] # Второй элемент с конца 
first_element = my_tuple[-6] # Последний элемент с конца, он же первый с начала   


print(last_element)  # Вывод: 'c'
print(second_to_last_element)  # Вывод: 'b'
print(first_element)  # Вывод: 1

Чтобы обратиться ко вложенным элементам, используйте двойную индексацию:

nested_tuple = (1, 2, (3, 4), 5)


# Обращение к элементам кортежа верхнего уровня
print(nested_tuple[0])  # Вывод: 1
print(nested_tuple[3])  # Вывод: 5


# Обращение к элементам вложенного кортежа (3, 4)
print(nested_tuple[2])  # Вывод: (3, 4)
print(nested_tuple[2][0])  # Вывод: 3
print(nested_tuple[2][1])  # Вывод: 4

Разберём код. Кортеж nested_tuple содержит вложенный кортеж (3, 4). Для доступа к элементам вложенного кортежа используем двойную индексацию: nested_tuple[2][0] обращается к первому элементу вложенного кортежа, а nested_tuple[2][1] обращается ко второму элементу.

Упаковка и распаковка

Упаковка (packing) и распаковка (unpacking) — это операции, которые позволяют создавать кортеж из набора значений и извлекать значения из кортежа в переменные. Рассмотрим их подробнее.

Упаковка кортежа. Значения 1, 2, 3 и 'hello' автоматически упаковываются в кортеж:

my_tuple = 1, 2, 3, 'hello'
# В переменной my_tuple теперь находится кортеж (1, 2, 3, 'hello')

Распаковка кортежа. Элементы кортежа извлекаются в переменные:

a, b, c, d = my_tuple
# Теперь переменные a, b, c, d содержат значения из кортежа
# a = 1, b = 2, c = 3, d = 'hello'

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

Посмотрим пример кода:

x = 5
y = 10
# Обмен значениями с использованием кортежа, упаковки и распаковки
x, y = y, x
# Теперь переменные x и y содержат новые значения
print('x =', x) # Вывод: x = 10
print('y =', y) # Вывод: y = 10

Операция упаковки (y, x) сначала создаёт кортеж из двух значений (10, 5), затем операция распаковки (x, y) распаковывает кортеж и присваивает значения переменным x и y соответственно. Теперь переменная x содержит 10, а y содержит 5.

Сравнение

Кортежи в Python сравниваются покомпонентно начиная с первого элемента до первого неравенства или до конца переменной. Если кортежи имеют одинаковую длину и все соответствующие элементы равны, то они считаются равными:

# Пример 1: кортежи с числовыми значениями
tuple1 = (1, 2, 3)
tuple2 = (1, 2, 3)
print(tuple1 == tuple2)  # True, так как все элементы равны


# Пример 2: кортежи с разными значениями
tuple3 = (4, 5, 6)
print(tuple1 == tuple3)  # False, так как первые элементы различаются


# Пример 3: Сравнение кортежей разной длины
tuple4 = (1, 2, 3, 4)
print(tuple1 == tuple4)  # False, так как длина кортежей разная

Для сравнения используются стандартные операторы ==, !=, >, <, >=, <=.

При сравнении используются правила:

  • когда сравниваются числовые элементы, большим считается тот кортеж, у которого первый отличающийся элемент больше;
  • когда сравниваются строки, сравнение происходит по порядку в алфавите;
  • элементы различных типов сравнивать нельзя — получим ошибку TypeError;
  • если длины кортежей различны, то кортеж с меньшей длиной считается наименьшим.

Пример:

tuple1 = (1, 2, 3)
tuple2 = (1, 2, 4)


print(tuple1 < tuple2)  # True, так как tuple1 меньше tuple2 — (tuple1[3] < tuple2[3])


tuple3 = ('apple', 'banana')
tuple4 = ('apple', 'orange')
print(tuple3 < tuple4)  # True, так как tuple3 «меньше» tuple4 по порядковому номеру первой отличающейся буквы


tuple7 = (1, 2, 3)
tuple8 = (1, 2, 3, 4)


print(tuple7 < tuple8)  # True, так как tuple7 «меньше» tuple8 (кортеж меньшей длины меньше)


tuple5 = (1, 2, 3)
tuple6 = ('apple', 'banana', 'orange')


print(tuple5 < tuple6)  


# Ошибка TypeError: '<' not supported between instances of 'int' and 'str' — нельзя сравнивать числа и строки

Проверка принадлежности элемента

Чтобы проверить, принадлежит ли элемент кортежу, используется оператор in. Если элемент присутствует в кортеже, оператор возвращает True, в противном случае — False.

my_tuple = (1, 2, 3, 4, 5)


# Проверка, содержится ли число 3 в кортеже


print(3 in my_tuple)  # Вывод: True

Перебор элементов

Для перебора элементов кортежа в Python используется цикл for или while:

my_tuple = (1, 2, 3, 4, 5)

# Перебор элементов кортежа с помощью цикла for
for element in my_tuple:
    print(element)

# Вывод:
1
2
3
4
5

# Перебор элементов кортежа с помощью цикла while
i = 0
while i < len(my_tuple):
    print(my_tuple[i])
    i += 1

Код выводит каждый элемент кортежа my_tuple на новой строке.

Удаление кортежа

Удалять из кортежа элементы нельзя, но можно удалить его полностью с помощью ключевого слова del:

my_tuple = (1, 2, 3, 4, 5)


# Удаление кортежа
del my_tuple
# Попробуем распечатать удалённый кортеж
print(my_tuple)  
# Ошибка: NameError: name 'my_tuple' is not defined

В этом примере del my_tuple удаляет ссылку на кортеж из памяти. После этого переменной my_tuple больше не существует и попытка обратиться к ней вызовет ошибку NameError.

Конкатенация и повторение

В Python для кортежей доступны операции конкатенации (сложения) и повторения (умножения). Эти операции могут использоваться при создании новых кортежей на основе существующих.

Конкатенация. Это объединение двух кортежей в один новый кортеж с помощью оператора +.

Напишем код:

tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)


concatenated_tuple = tuple1 + tuple2


print('Конкатенация кортежей:', concatenated_tuple)

Результат:

Конкатенация кортежей: (1, 2, 3, 4, 5, 6)

Повторение. Этот способ создания кортежа напоминает арифметическое умножение: справа от исходного кортежа нужно добавить оператор * и указать, сколько раз он повторится.

original_tuple = (1, 2, 3)


repeated_tuple = original_tuple * 3


print('Повторение кортежа:', repeated_tuple)

Результат выполнения кода:

Повторение кортежа: (1, 2, 3, 1, 2, 3, 1, 2, 3)

При выполнении операций конкатенации и повторения создаются новые кортежи, а исходные остаются неизменными.

Функции кортежей Python

В Python есть встроенные функции, которые облегчают работу с кортежами.

Во многих статьях можно встретить формулировку «методы кортежей», но это не совсем корректно. Метод — это понятие из объектно-ориентированного программирования, обозначающее функцию или процедуру, принадлежащую к какому-либо классу или объекту. Ниже мы говорим про функции, которые принимают и возвращают значения, без привязки к классам или объектам.

Определение длины, суммы, минимального и максимального элемента

Длину кортежа можно получить функцией len(), которая возвращает количество элементов в кортеже:

my_tuple = (1, 2, 3, 4, 5)


length_of_tuple = len(my_tuple)


print('Длина кортежа:', length_of_tuple)

Результат:

Длина кортежа: 5

Сумма элементов рассчитывается легко запоминающейся функцией sum():

my_tuple = (1, 2, 3, 4, 5)
sum_of_elements = sum(my_tuple)
print('Сумма элементов кортежа:', sum_of_elements)

Результат:

Сумма элементов кортежа: 15

Если кортеж пуст, len() и sum() возвращают 0.

Минимальный и максимальный элементы кортежа можно получить с помощью функций min() и max():

my_tuple = (1, 2, 3, 4, 5)


min_element = min(my_tuple)
max_element = max(my_tuple)


print('Минимальный элемент кортежа:', min_element)
print('Максимальный элемент кортежа:', max_element)

Результат выполнения:

Минимальный элемент кортежа: 1
Максимальный элемент кортежа: 5

Если кортеж пуст, то использование функций min() и max() вызовет ошибку ValueError.

Сортировка кортежа

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

Для сортировки используется функция sorted():

# Исходный кортеж
original_tuple = (3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)


# Создаём новый кортеж с отсортированными элементами
sorted_tuple = tuple(sorted(original_tuple))


# Выводим результат
print('Исходный кортеж:', original_tuple)
print('Отсортированный кортеж:', sorted_tuple)

Результат:

Исходный кортеж: (3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)
Отсортированный кортеж: (1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9)

Остановимся на коде:

  • sorted(original_tuple) создаёт новый список, содержащий отсортированные элементы из original_tuple;
  • tuple(...) создаёт новый кортеж из отсортированного списка.

Если нужна сортировка в обратном порядке, в функции sorted() используется параметр reverse=True:

original_tuple = (3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)


sorted_tuple_reverse = tuple(sorted(original_tuple, reverse=True))


print('Отсортированный в обратном порядке кортеж:', sorted_tuple_reverse)

Получаем:

Отсортированный в обратном порядке кортеж: (9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1)

Срезы в кортежах

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

Для определения начала и конца среза можно использовать положительные и отрицательные индексы:

  • левый индекс указывает на элемент, с которого начинается срез;
  • правый индекс указывает на элемент, которым заканчивается срез, этот элемент в срез не включается.

Получим срез, указав положительные индексы:

my_tuple = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)


# Получение среза с элементами от 2 до 6 (не включая 6)
subset_positive = my_tuple[2:6]


print('Срез с положительными индексами:', subset_positive)

Результат:

Срез с положительными индексами: (2, 3, 4, 5)

Срез с отрицательными индексами:

my_tuple = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)


# Срез с отрицательными индексами: начинаем с элемента с индексом -4 и заканчиваем элементом с индексом -1 (не включительно)
negative_slice = my_tuple[-4:-1]


print('Срез с отрицательными индексами:', negative_slice)

Результат:

Срез с отрицательными индексами: (6, 7, 8)

Если индексы пропущены, то срез будет включать все элементы от начала кортежа до заданного конца среза или от заданного начала среза до конца кортежа:

my_tuple = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)


# Все элементы от начала кортежа до 7-го элемента (не включительно)
slice_from_start = my_tuple[:7]


# Все элементы от 3-го до конца кортежа
slice_to_end = my_tuple[3:]


print('Срез от начала до 7-го элемента:', slice_from_start)
print('Срез от 3-го до конца:', slice_to_end)

Результат:

Срез от начала до 7-го элемента: (0, 1, 2, 3, 4, 5, 6)
Срез от 3-го до конца: (3, 4, 5, 6, 7, 8, 9)

Преобразование в другие типы данных

В Python можно преобразовывать кортежи в другие типы данных: списки, строки, множества или словари.

Так можно превратить кортеж в список:

my_tuple = (1, 2, 3, 4, 5)


# Преобразование кортежа в список
my_list = list(my_tuple)


print('Кортеж:', my_tuple)
print('Список:', my_list)

Результат:

Кортеж: (1, 2, 3, 4, 5)
Список: [1, 2, 3, 4, 5]

А так можно преобразовать кортеж в строку:

my_tuple = (1, 2, 3)


# Преобразование кортежа в строку
my_string = ''.join(map(str, my_tuple))


print('Кортеж:' my_tuple)
print('Строка:', my_string)

Здесь использовали встроенную функцию str.join. Работает она просто — переводит каждый элемент кортежа в строковый тип, а затем объединяет их в одну строку.

Результат:

Кортеж: (1, 2, 3)
Строка: 123

Преобразовать кортеж во множество:

my_tuple = (1, 2, 3, 2, 4)


# Преобразование кортежа во множество, при котором удаляются повторяющиеся элементы
my_set = set(my_tuple)


print('Кортеж:', my_tuple)
print('Множество:', my_set)

Результат:

Кортеж: (1, 2, 3, 2, 4)
Множество: {1, 2, 3, 4}

Множества — это неупорядоченные коллекции, которые состоят из уникальных элементов. Если преобразовать кортеж во множество, то все дубликаты в нём удалятся.

Кортеж в словарь (пары «ключ — значение»):

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


# Преобразование кортежа в словарь
my_dict = dict(my_tuple)


print('Кортеж:', my_tuple)
print('Словарь:', my_dict)

Результат:

Кортеж: (('a', 1), ('b', 2), ('c', 3))
Словарь: {'a': 1, 'b': 2, 'c': 3}

Как можно изменить элементы

Хотя кортежи относятся к неизменяемым элементам, есть трюк, который позволяет их изменять. Для этого нужно перевести кортеж в список, сделать необходимые преобразования, а затем превратить полученный список в кортеж:

my_tuple = (1, 2, 3, 4, 5)


# Преобразование кортежа в список
my_list = list(my_tuple)


# Изменение значения в списке
my_list[2] = 10


# Преобразование списка обратно в кортеж
updated_tuple = tuple(my_list)


print('Исходный кортеж:', my_tuple)
print('Обновлённый кортеж:', updated_tuple)

Результат:

Исходный кортеж: (1, 2, 3, 4, 5)
Обновлённый кортеж: (1, 2, 10, 4, 5)

Другой подоход — создать новый кортеж с изменёнными значениями:

my_tuple = (1, 2, 3, 4, 5)


# Создание нового кортежа с изменённым значением
updated_tuple = my_tuple[:2] + (10,) + my_tuple[3:]


print('Исходный кортеж:', my_tuple)
print('Обновлённый кортеж:', updated_tuple)

Результат:

Исходный кортеж: (1, 2, 3, 4, 5)
Обновлённый кортеж: (1, 2, 10, 4, 5)

В этом примере создаём новый кортеж updated_tuple, включая все элементы кортежа my_tuple с начала до второго, добавляем к ним новое значение 10, а затем добавляем все элементы my_tuple начиная с четвёртого и до конца.

Мы рассмотрели только базовые понятия и операции с кортежами. Если вы хотите погрузиться в работу с ними глубже, то советуем перейти к документации. И обязательно пишите код из примеров в своём редакторе кода или IDE — это поможет закрепить теорию.

Больше интересного про код — в нашем телеграм-канале.  Подписывайтесь!

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Python-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована