Кортежи
До этого момента мы встречались только с примитивными типами — строка, число, булев тип. Ещё нам знакомы функции и модули с пакетами (да, в Python модули и пакеты, это тоже значения специальных встроенных типов). Но часто в программировании приходится создавать более сложные значения, чем числа и строки, и манипулировать такими значениями. Именно поэтому во многих языках программирования есть составные типы. Значение составного типа может состоять как из значений примитивных типов, так и из значений других составных типов, таким образом составные типы позволяют описывать сущности произвольной сложности — и шахматные доски, и космические ракеты!
В этом уроке мы познакомимся с самым простым, но очень полезным составным типом — кортежем (в англоязычных текстах он известен как tuple).
Кортежи
Кортеж — это несколько значений, записанных через запятую. Да, всё очень просто! Вот несколько примеров:
rgb_colour = (255, 127, 64) name_and_age = ('Bob', 42) three_booleans = (True, False, True) two_pairs_of_numbers = ((1, 2), (3, 4))
Определять кортежи очень просто, сложности могут возникнуть только с кортежами, содержащими ровно один элемент. Если мы просто укажем значение в скобках, то Python подумает, что мы хотим посчитать арифметическое выражение со скобками:
not_a_tuple = (42) # 42
Чтобы сказать пайтону, что мы хотим создать именно кортеж, нужно поставить после элемента кортежа запятую:
tuple = (42,) # (42,)
Да, форма записи довольно необычная, но вы привыкнете :)
Возврат нескольких значений из функции
Кортежи очень полезны, когда нам нужно вернуть из функции сразу несколько значений. Так, функция, которая принимает два аргумента-числа и возвращает одновременно результат деления нацело и остаток от деления, будет выглядеть так:
def div_mod(a, b): quotient = a // b modulo = a % b return (quotient, modulo) div_mod(13, 4) # (3, 1)
Получение элементов кортежа по индексу
Выше мы только создавали кортежи. Теперь научимся их разбирать! В простейшем случае достаточно обратиться к элементу кортежа по индексу:
name_and_age = ('Bob', 42) name_and_age[0] # 'Bob' name_and_age[1] # 42
Также у кортежа есть длина, которую, как и для строки, можно получить с помощью функции len
:
tuple = (42,) # (42,) len(tuple) # 1 pair = (1, 2) # (1, 2) len(pair) # 2
Деструктуризация
Обращение по индексу, это не самый удобный способ работы с кортежами. Дело в том, что кортежи часто содержат значения разных типов, и помнить, по какому индексу что лежит — очень непросто. Но есть способ лучше! Как мы кортеж собираем, так его можно и разобрать:
name_and_age = ('Bob', 42) (name, age) = name_and_age name # 'Bob' age # 42
Именно таким способом принято получать и сразу разбирать значения, которые возвращает функция (если таковая возвращает несколько значений, конечно):
(quotient, modulo) = div_mod(13, 4)
Соответственно кортеж из одного элемента нужно разбирать так:
(a,) = (42,) a # 42
Если же после имени переменной не поставить запятую, то синтаксической ошибки не будет, но в переменную a
кортеж запишется целиком, т.е. ничего не распакуется. Всегда помните о запятых!
Кортежи, множественное присваивание и обмен значениями
Благодаря тому, что кортежи легко собирать и разбирать, в Python удобно делать такие вещи, как множественное присваивание. Смотрите:
(a, b, c) = (1, 2, 3) a # 1 b # 2 c # 3
Используя множественное присваивание, можно провернуть интересный трюк: обмен значениями между двумя переменными. Вот код:
a = 100 b = 'foo' (a, b) = (b, a) a # 'foo' b # 100
Cтрочку (a, b) = (b, a)
нужно понимать как "присвоить в а
и b
значения из кортежа, состоящего из значений переменных b
и a
".