Недавно мы изучали списки в Python — многофункциональный и удобный вид структуры для работы с данными. Сегодня черёд кортежей. Они во многом похожи на списки, но и отличаются во многом. Рассказываем и показываем на подробных примерах. Приготовьтесь: получилась большая статья.
Что такое кортеж
Кортеж tuple
— это упорядоченная и неизменяемая коллекция объектов различных типов. По сути, кортежи — те же списки, только для них недействительны все операции и методы, которые обновляют коллекцию. Кортежи не сортируются сами по себе, не принимают новые элементы и не перезаписывают те, что уже есть.
Чтобы создать кортеж, достаточно перечислить его элементы через запятую: Python автоматически распознает эту последовательность как кортеж. Но обычно рекомендуется использовать круглые скобки — так код получается яснее и читабельнее. Например, мы хотим создать кортеж с чётными числами от 2 до 14:
my_tuple = (2, 4, 6, 8, 10, 12, 14)
Такой же кортеж можно создать при помощи встроенного метода tuple
и функции range
, которая создаёт последовательность чисел. Укажем через запятую начало, конец последовательности и шаг, с которым нужно генерировать числа. При этом число, обозначающее конец последовательности, не будет включено:
my_tuple = tuple(range(2, 16, 2))
Ещё раз подробно перечислим свойства кортежей:
- Гибкость. Как и списки, кортежи могут содержать элементы разных типов данных: целые числа, числа с плавающей запятой, строки, кортежи, словари и другие объекты Python.
- Неизменяемость. Элементы в кортежах нельзя сортировать, добавлять, изменять и удалять. Но можно преобразовать кортеж в список, внести изменения и снова сделать кортеж.
- Упорядоченность. Порядок элементов имеет значение, благодаря чему элементы кортежа доступны по индексу (индексация начинается с 0).
Операции над кортежами
Кортежам присущи все операции списков, кроме операции удаления элемента командой del
. Создадим кортеж из названий шести фруктов и рассмотрим доступные операции на его примере:
my_fruits = ('яблоко', 'апельсин', 'груша', 'грейпфрут', 'айва', 'абрикос')
Получение длины. С помощью функции len()
можно узнать, сколько элементов содержится в кортеже:
# присваиваем переменной значение количества элементов
length = len(my_fruits)
# выводим результат
print(f'''my_fruits = {my_fruits}
Количество фруктов в кортеже: {length}''')

Доступ по индексу. Как и в списках, индексация ведётся с нуля, поэтому номер последнего элемента всегда будет на единицу меньше длины кортежа. Если индексы отрицательные, обращение к элементам будет производиться с конца кортежа.
Например, мы можем вывести третий, предпоследний и последний элементы из нашего кортежа:
print(f'''my_fruits = {my_fruits}
Избранные фрукты: {my_fruits[2]}, {my_fruits[-2]}, {my_fruits[length - 1]}''')

По индексу также можно присвоить элементы кортежа другим переменным для дальнейшей работы с ними:
# присваиваем переменной элемент с индексом 2
my_fruit1 = my_fruits[2]
# присваиваем переменной элемент с индексом −2 (предпоследний)
my_fruit2 = my_fruits[-2]
# присваиваем переменной последний элемент кортежа
last_fruit = my_fruits[length - 1]
# выводим результаты
print(f'''my_fruit1 = {my_fruit1}
my_fruit2 = {my_fruit2}
last_fruit = {last_fruit}''')

Срезы. Срезы выбирают из кортежа подмножества. Синтаксис такой же, как для списков: нужно указать в квадратных скобках начальный и конечный индексы элементов (индексация начинается с 0). Элемент с последним указанным индексом не включается в срез. Срез с диапазоном [::]
создаёт копию кортежа.
# выбираем часть кортежа с нулевого по четвёртый элементы
my_fruits_part1 = my_fruits[0:5]
# выбираем элементы с четвёртого и до конца
my_fruits_part2 = my_fruits[4:]
# выбираем элементы с третьего по пятый
my_fruits_part3 = my_fruits[2:-1]
# выбираем элементы с нулевого по второй
my_fruits_part4 = my_fruits[:-3]
# выбираем элементы с предпоследнего и до конца
my_fruits_part5 = my_fruits[-2:]
# выбираем элементы с начала, шагая через 2
my_fruits_part6 = my_fruits[::2]
# выбираем в обратном порядке, шагая через 1
my_fruits_reversed = my_fruits[::-1]
# выводим результаты
print(f'''my_fruits_part1 = {my_fruits_part1}
my_fruits_part2 = {my_fruits_part2}
my_fruits_part3 = {my_fruits_part3}
my_fruits_part4 = {my_fruits_part4}
my_fruits_part5 = {my_fruits_part5}
my_fruits_part6 = {my_fruits_part6}
my_fruits_reversed = {my_fruits_reversed}''')

Конкатенация. Кортежи можно складывать между собой, тогда Python создаст новый кортеж, а исходные не изменятся:
# новый кортеж фруктов
my_fruits_new = ('мандарин', 'гранат', 'киви')
# объединённый кортеж
my_fruits_concatenated = my_fruits + my_fruits_new
# выводим результат
print(f'Объединённый кортеж фруктов: {my_fruits_concatenated}')

Удаление всего кортежа. Кортеж нельзя удалить напрямую, но можно удалить ссылку на него с помощью функции del
. Если на кортеж нет других ссылок, сборщик мусора Python автоматически удалит его и освободит память.
Если удалить кортеж, при выводе мы получим ошибку.
del my_fruits_part1
print(f'my_fruits_part1 = {my_fruits_part1}')

Умножение на целое число. Умножив кортеж на N, мы создадим новый кортеж из N исходных кортежей:
multiplied_fruits = my_fruits * 3
print(f'Кортеж фруктов после умножения на 3: {multiplied_fruits}')

Проверка наличия элемента. Оператор in
проверяет наличие элемента в кортеже, not in
— отсутствие:
# проверяем наличие в кортеже элемента “киви”
flag = 'киви' in my_fruits
print(f'flag = {flag}')

# проверяем отсутствие в кортеже элемента “киви”
flag = 'киви' not in my_fruits
print(f'flag = {flag}')

Минимум и максимум. С помощью функций min()
и max()
можно определять минимальное и максимальное значения. Числовые значения сравниваются по величине, строки — по их числовым значениям в таблице символов Unicode.
# элемент с минимальным значением
my_fruits_min = min(my_fruits)
# выводим результат
print(f'my_fruits_min = {my_fruits_min}')
# элемент с максимальным значением
my_fruits_max = max(my_fruits)
# выводим результат
print(f'my_fruits_max = {my_fruits_max}')

Сортировка без изменения. Функция sorted()
вернёт отсортированный кортеж без его изменения:
# сортируем кортеж
my_fruits_sorted = sorted(my_fruits)
print(f'''Кортеж фруктов: {my_fruits}
Отсортированный кортеж фруктов: {my_fruits_sorted}''')

Сравнение кортежей. Как и списки, кортежи сравниваются поэлементно, пока не найдётся больший из них. Подмножество элементов кортежа всегда меньше него. При сравнении строк элементы с равными индексами сравниваются по их числовым значениям в таблице символов Unicode.
# выводим результат проверки, что исходный кортеж меньше объединённого
print(my_fruits < my_fruits_concatenated)

Методы кортежей
У кортежей в силу неизменяемости только два метода: .index
и .count
. Действуют так же, как со списками.
Метод .index возвращает индекс элемента:
index_of_pear = my_fruits.index('груша')
print(f'Индекс элемента "груша" в кортеже: {index_of_pear}')

Метод .count возвращает число вхождений элемента в кортеж:
frequency_of_kiwi = my_fruits.count('киви')
print(f'Количество вхождений элемента "киви" в кортеж фруктов: {frequency_of_kiwi}')

Чем кортеж лучше списка
Кортежи хороши тем, что их нельзя случайно изменить. Они занимают меньше памяти, чем списки. Например, пустой список занимает 56 байт, тогда как пустой кортеж — всего 40 байт:
# подключаем модуль sys для работы с операционной системой
import sys
# создаём пустой список
empty_list = []
# создаём пустой кортеж для сравнения
empty_tuple = ()
# выводим размер пустого списка
print(f'Размер пустого списка: {sys.getsizeof(empty_list)}')
# выводим размер пустого кортежа
print(f'Размер пустого кортежа: {sys.getsizeof(empty_tuple)}')

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