Основы работы с кортежами

  1. Функция tuple()
  2. Особенности кортежей
  3. Вложенные кортежи
  4. Перебор кортежей
  5. Сравнение кортежей
  6. Сортировка кортежей
  7. Преобразование кортежа в список и строку
  8. Упаковка кортежей
  9. Распаковка кортежей

Функция tuple()


Встроенная функция list() может применяться для преобразования кортежа в список.

Приведенный ниже код:

number_tuple = (1, 2, 3, 4, 5)
number_list = list(number_tuple)
print(number_list)

выводит:

[1, 2, 3, 4, 5]

Встроенная функция tuple()  может применяться для преобразования списка в кортеж.

Приведенный ниже код:

str_list = ['один', 'два', 'три']
str_tuple = tuple(str_list)
print(str_tuple)

выводит:

('один', 'два', 'три')

Аналогичным образом мы можем создать кортеж на основании строки.

Приведенный ниже код:

text = 'hello python'
str_tuple = tuple(text)
print(str_tuple)

выводит:

('h', 'e', 'l', 'l', 'o', ' ', 'p', 'y', 't', 'h', 'o', 'n')

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

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

s = 'симпотичный'
print(s)

a = list(s)
a[4] = 'а'
s = ''.join(a)
print(s)

Приведенный выше код выводит:

симпотичный
симпатичный

С этой же целью может потребоваться преобразование кортежа в список:

writer = ('Лев Толстой', 1827)
print(writer)

a = list(writer)
a[1] = 1828
writer = tuple(a)
print(writer)

Приведенный выше код выводит:

('Лев Толстой', 1827)
('Лев Толстой', 1828)

Особенности кортежей

Кортежи поддерживают те же операции, что и списки, за исключением изменяющих содержимое.

Кортежи поддерживают:

Вложенные кортежи

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

Следующий программный код:

colors = ('red', ('green', 'blue'), 'yellow')
numbers = (1, 2, (4, (6, 7, 8, 9)), 10, 11)

print(colors[1][1])
print(numbers[2][1][3])

выводит:

blue
9

Пример со списочным выражением

Дополните приведенный код так, чтобы переменная new_tuples содержала список кортежей на основе списка tuples с последним элементом каждого кортежа, замененным на численное значение 100

tuples = [(10, 20, 40), (40, 50, 60), (70, 80, 90), (10, 90), (1, 2, 3, 4), (5, 6, 10, 2, 1, 77)] new_tuples = [i[:-1] + (100,) for i in tuples]

Перебор кортежей

Перебор элементов кортежа осуществляется точно так же как перебор элементов списка.

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

Вариант 1. Если нужны индексы элементов:

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

for i in range(len(numbers)):
    print(numbers[i])

Вариант 2. Если индексы не нужны:

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

for num in numbers:
    print(num)

Можно также использовать операцию распаковки кортежа.

Приведенный ниже код:

numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
languages = ('Python', 'C++', 'Java')

print(*numbers)
print(*languages, sep='\n')

выводит:

0 1 2 3 4 5 6 7 8 9 10
Python
C++
Java

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

Кортежи можно сравнивать между собой.

Приведенный ниже код:

print((1, 8) == (1, 8))
print((1, 8) != (1, 10))
print((1, 9) < (1, 2))
print((2, 5) < (6,))
print(('a', 'bc') > ('a', 'de'))

выводит:

True
True
False
True
False

Обратите внимание: операции == и != применимы к любым кортежам, независимо от типов элементов. А вот операции <><=>= применимы только в том случае, когда соответствующие элементы кортежей имеют один тип.

Приведенный ниже код:

print((7, 5) < ('java', 'python'))

выводит:

TypeError: '<' not supported between instances of 'int' and 'str'

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

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

Как мы помним, списки имеют метод sort(), который осуществляет сортировку на месте, то есть меняет порядок исходного списка. Поскольку кортежи по своей природе неизменяемы, то встроенного метода sort() они не содержат, тем не менее с помощью встроенной функции sorted() (не путать с списочным методом sort()) мы можем сортировать значения в кортежах.

Приведенный ниже код:

not_sorted_tuple = (34, 1, 8, 67, 5, 9, 0, 23)
print(not_sorted_tuple)

sorted_tuple = tuple(sorted(not_sorted_tuple))
print(sorted_tuple)

выводит:

(34, 1, 8, 67, 5, 9, 0, 23)
(0, 1, 5, 8, 9, 23, 34, 67)

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

Для сортировки кортежа можно воспользоваться явным преобразованием в список и использовать метод sort():

not_sorted_tuple = ('cc', 'aa', 'dd', 'bb')
tmp = list(not_sorted_tuple)
tmp.sort()

sorted_tuple = tuple(tmp)
print(sorted_tuple)

Преобразование кортежа в список и строку

Часто на практике нам приходится преобразовывать кортежи в списки и в строки. Для этого используются функции и методы str(), list(), tuple(), join().

Преобразование кортежа в список и наоборот

Кортеж можно преобразовать в список с помощью функции list().

Приведенный ниже код:

tuple1 = (1, 2, 3, 4, 5)
list1 = list(tuple1)
print(list1)

выводит:

[1, 2, 3, 4, 5]

Список можно преобразовать в кортеж с помощью функции tuple().

Приведенный ниже код:

list1 = [1, 17.8, 'Python']
tuple1 = tuple(list1)
print(tuple1)

выводит:

(1, 17.8, 'Python')

Преобразование кортежа в строку и наоборот

Кортеж можно преобразовать в строку с помощью строкового метода join().

Приведенный ниже код:

notes = ('Do', 'Re', 'Mi', 'Fa', 'Sol', 'La', 'Si')
string1 = ''.join(notes)
string2 = '.'.join(notes)

print(string1)
print(string2)

выводит:

DoReMiFaSolLaSi
Do.Re.Mi.Fa.Sol.La.Si

Обратите внимание, что для применения строкового метода join() кортеж должен содержать именно строковые элементы. Если элементы кортежа отличны от строк, то требуется предварительно их преобразовать.

Строку можно преобразовать в кортеж с помощью функции tuple().

Приведенный ниже код:

letters = 'abcdefghijkl'
tpl = tuple(letters)
print(tpl)

выводит:

('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l')

Обратите внимание, что следующий код:

number = 12345
tpl = tuple(number)
print(tpl)

приведет к ошибке:

TypeError: 'int' object is not iterable

Это происходит, поскольку тип данных int не является итерируемым объектом. Для преобразования числа в кортеж сначала нужно число преобразовать в строку и уже только потом использовать функцию tuple().

Упаковка кортежей

Упаковкой кортежа называют присваивание его какой-либо переменной.

Приведенный ниже код:

tuple1 = (1, 2, 3)
tuple2 = ('b',)
tuple3 = ('red', 'green', 'blue', 'cyan')

print(type(tuple1))
print(type(tuple2))
print(type(tuple3))

выводит:

<class 'tuple'>
<class 'tuple'>
<class 'tuple'>

Обратите внимание на то, что упаковка выполняется всегда, когда справа от знака равенства стоит больше одного значения.

Приведенный ниже код автоматически запакует 1, 2, 3 и 'b', в кортежи (1, 2, 3) и ('b', ) и присвоит их значения переменным tuple1 и tuple2:

tuple1 = 1, 2, 3
tuple2 = 'b',

print(type(tuple1))
print(type(tuple2))

выводит:

<class 'tuple'>
<class 'tuple'>

Распаковка кортежей

Обратная операция, смысл которой в том, чтобы присвоить значения элементов кортежа отдельным переменным, называется распаковкой кортежа.

Приведенный ниже код:

colors = ('red', 'green', 'blue', 'cyan')

(a, b, c, d) = colors

print(a)
print(b)
print(c)
print(d)

выводит:

red
green
blue
cyan

В приведенном примере кортеж colors распаковывается в переменные a, b, c, d.

Мы можем опустить скобки слева от знака равенства:

colors = ('red', 'green', 'blue', 'cyan')
a, b, c, d = colors

Количество переменных должно совпадать с числом элементов в кортеже.

Приведенный ниже код:

colors = ('red', 'green', 'blue', 'cyan')
a, b = colors

приводит к ошибке:

ValueError: too many values to unpack

Аналогично, приведенный ниже код:

colors = ('red', 'green', 'blue')
a, b, c, d = colors

приводит к ошибке:

ValueError: not enough values to unpack (expected 4, got 3)

Однако, если необходимо получить лишь какие-то отдельные значения, то в качестве "ненужных" переменных позволено использовать символ нижнего подчеркивания _.

Приведенный ниже код:

colors = ('red', 'green', 'blue')
a, b, _ = colors

print(a)
print(b)

выводит:

red
green

Распаковка кортежей очень удобна на практике. По сути мы использовали ее, когда меняли местами значения двух переменных без использования временных переменных.

Приведенный ниже код:

a = 7
b = 17
a, b = b, a

print(a, b)

выводит:

17 7

Сначала вычисляются все значения справа, и лишь затем они кладутся в левую часть оператора присваивания. Поэтому можно менять местами значения переменных a и b, написав: a, b = b, a.

Приведенный ниже код:

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

print(b, c, a)

выводит:

1 2 3

* при распаковке кортежей

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

Рассмотрим программный код:

a, b, *tail = 1, 2, 3, 4, 5, 6

В этом случае в переменной a будет записана единица, в переменной b — двойка, а в переменной tail — список, состоящий из всех аргументов, которые не попали в предыдущие переменные. В данном случае tail будет равен [3, 4, 5, 6].

Учтите, что tail всегда будет списком, даже когда в него попадает лишь один элемент или даже ноль.

Приведенный ниже код:

a, b, *tail = 1, 2, 3

print(tail)

выводит:

[3]

Приведенный ниже код:

a, b, *tail = 1, 2

print(tail)

выводит:

[]

Звездочка может быть только у одного аргумента, но необязательно у последнего.

Приведенный ниже код:

*names, surname = ('Стефани', 'Джоанн', 'Анджелина', 'Джерманотта')

print(names)
print(surname)

выводит:

['Стефани', 'Джоанн', 'Анджелина']
Джерманотта

Аргумент со звездочкой может стоять и посередине.

singer = ('Freddie', 'Bohemian Rhapsody', 'Killer Queen', 'Love of my life', 'Mercury')

name, *songs, surname = singer

print(name)
print(songs)
print(surname)

выводит:

Freddie
['Bohemian Rhapsody', 'Killer Queen', 'Love of my life']
Mercury

Примечания

Примечание 1. Если вы хотите распаковать единственное значение в кортеже, после имени переменной должна идти запятая.

Приведенный ниже код:

a = 1,      # не распаковка, а просто присвоение
b, = 1,     # распаковка

print(a)
print(b)

выводит:

(1,)
1

Примечание 2. Распаковывать можно не только кортеж, правая сторона может быть любой последовательностью (кортеж, строка или список).

info = ['timur', 'beegeek.org']
user, domain = info    # распаковка списка

print(user)
print(domain)

a, b, c, d = 'math'    # распаковка строки

print(a)
print(b)
print(c)
print(d)

выводит:

timur
beegeek.org
m
a
t
h

Примечание 3. Помимо метода split() строковый тип данных содержит метод partition(). Метод partition() принимает на вход один аргумент sep, разделяет строку при первом появлении sep и возвращает кортеж, состоящий из трех элементов: часть перед разделителем, сам разделитель и часть после разделителя. Если разделитель не найден, то кортеж содержит саму строку, за которой следуют две пустые строки.

Приведенный ниже код:

s1 = 'abc-de'.partition('-')
s2 = 'abc-de'.partition('.')
s3 = 'abc-de-fgh'.partition('-')

print(s1)
print(s2)
print(s3)

выведет:

('abc', '-', 'de')
('abc-de', '', '')
('abc', '-', 'de-fgh')

Примечание 4. С использованием кортежей многие алгоритмы приобретают достаточно краткую форму. Например, вычисление чисел Фибоначчи может выглядеть следующим образом:

n = int(input())
f1, f2 = 1, 1
for i in range(n):
    print(f1)
    f1, f2 = f2, f1 + f2