Кортежи (tuple)
Сегодня я расскажу о таком типе данных, как кортежи (tuple) и о том, где они применяются.
Кортеж, по сути — неизменяемый список.
Зачем нужны кортежи, если есть списки?
- Защита от дурака. То есть кортеж защищен от изменений, как намеренных (что плохо), так и случайных (что хорошо).
- Меньший размер. Дабы не быть голословным:
Как работать с кортежами?
С преимуществами кортежей разобрались, теперь встает вопрос — а как с ними работать. Примерно так же, как и со списками.
Создаем пустой кортеж:
Создаем кортеж из одного элемента:
Ну и создать кортеж из итерируемого объекта можно с помощью все той же пресловутой функции tuple()
Операции с кортежами
Все операции над списками, не изменяющие список (сложение, умножение на число, методы index() и count() и некоторые другие операции). Можно также по-разному менять элементы местами и так далее.
Например, гордость программистов на python - поменять местами значения двух переменных:
Для вставки кода на Python в комментарий заключайте его в теги
- Модуль csv - чтение и запись CSV файлов
- Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
- Онлайн-обучение Python: сравнение популярных программ
- Книги о Python
- GUI (графический интерфейс пользователя)
- Курсы Python
- Модули
- Новости мира Python
- NumPy
- Обработка данных
- Основы программирования
- Примеры программ
- Типы данных в Python
- Видео
- Python для Web
- Работа для Python-программистов
- Сделай свой вклад в развитие сайта!
- Самоучитель Python
- Карта сайта
- Отзывы на книги по Python
- Реклама на сайте
Что такое кортеж в python
Кортеж (tuple) представляет последовательность элементов, которая во многом похожа на список за тем исключением, что кортеж является неизменяемым (immutable) типом. Поэтому мы не можем добавлять или удалять элементы в кортеже, изменять его.
Для создания кортежа используются круглые скобки, в которые помещаются его значения, разделенные запятыми:
tom = ("Tom", 23) print(tom) # ("Tom", 23)
Также для определения кортежа мы можем просто перечислить значения через запятую без применения скобок:
tom = "Tom", 23 print(tom) # ("Tom", 23)
Если вдруг кортеж состоит из одного элемента, то после единственного элемента кортежа необходимо поставить запятую:
tom = ("Tom",)
Для создания кортежа из другого набора элементов, например, из списка, можно передать список в функцию tuple() , которая возвратит кортеж:
data = ["Tom", 37, "Google"] tom = tuple(data) print(tom) # ("Tom", 37, "Google")
С помощью встроенной функции len() можно получить длину кортежа:
tom = ("Tom", 37, "Google") print(len(tom)) # 3
Обращение к элементам кортежа
Обращение к элементам в кортеже происходит также, как и в списке, по индексу. Индексация начинается также с нуля при получении элементов с начала списка и с -1 при получении элементов с конца списка:
tom = ("Tom", 37, "Google", "software developer") print(tom[0]) # Tom print(tom[1]) # 37 print(tom[-1]) # software developer
Но так как кортеж - неизменяемый тип (immutable), то мы не сможем изменить его элементы. То есть следующая запись работать не будет:
tom[1] = "Tim"
При необходимости мы можем разложить кортеж на отдельные переменные:
name, age, company, position = ("Tom", 37, "Google", "software developer") print(name) # Tom print(age) # 37 print(position) # software developer print(company) # Google
Получение подкортежей
Как и в списках, можно получить часть кортежа в виде другого кортежа
tom = ("Tom", 37, "Google", "software developer") # получем подкортеж с 1 по 3 элемента (не включая) print(tom[1:3]) # (37, "Google") # получем подкортеж с 0 по 3 элемента (не включая) print(tom[:3]) # ("Tom", 37, "Google") # получем подкортеж с 1 по послдений элемент print(tom[1:]) # (37, "Google", "software developer")
Кортеж как параметр и результат функций
Особенно удобно использовать кортежи, когда необходимо возвратить из функции сразу несколько значений. Когда функция возвращает несколько значений, фактически она возвращает в кортеж:
def get_user(): name = "Tom" age = 22 company = "Google" return name, age, company user = get_user() print(user) # ("Tom", 37, "Google")
При передаче кортежа в функцию с помощью оператора * его можно разложить на отдельные значения, которые передаются параметрам функции:
def print_person(name, age, company): print(f"Name: Age: Company: ") tom = ("Tom", 22) print_person(*tom, "Microsoft") # Name: Tom Age: 22 Company: Microsoft bob = ("Bob", 41, "Apple") print_person(*bob) # Name: Bob Age: 41 Company: Apple
Перебор кортежей
Для перебора кортежа можно использовать стандартные циклы for и while . С помощью цикла for:
tom = ("Tom", 22, "Google") for item in tom: print(item)
С помощью цикла while:
tom = ("Tom", 22, "Google") i = 0 while i < len(tom): print(tom[i]) i += 1
Проверка наличия значения
Как для списка с помощью выражения элемент in кортеж можно проверить наличие элемента в кортеже:
user = ("Tom", 22, "Google") name = "Tom" if name in user: print("Пользователя зовут Tom") else: print("Пользователь имеет другое имя")
Упаковка данных в Python — кортеж tuple
Вас зовут get_contacts и вы умеете находить контакты человека по email-адресу: его адрес, имя и номер телефона. Вы не прочь поделиться информацией с другими, но Python вам это запрещает. Нельзя возвращать так много данных разом, результат у функции может быть только один. Вы можете выбрать что-то одно, самое важное: адрес, имя, или телефон человека. Или можете проявить изобретательность и упаковать все свои данные в одну переменную.
Как упаковать данные в кортеж
Для функции get_contacts(email) доступны несколько способов упаковки данных в более сложную структуру: словарь dict() , кортеж tuple() и еще несколько других. Рассмотрим подробнее последний вариант — tuple , или по-русски кортеж.
Предположим, вы вызвали функцию get_contacts('dmitry@example.com') , она нашла такого человека и хочет вернуть его контакты:
full_name = 'Никифоров Дмитрий Анатольевич' city = 'Москва' phone_number = '929-876-54-32'
Функция создает кортеж — tuple() —, чтобы поместить в него все контакты:
contacts = (full_name, city, phone_number)
Круглые скобки и запятые указывают Python, что из перечисленных переменных full_name , city и phone_number нужно создать новую структуру данных:
print(type(contacts)) # выведет print(contacts)
Последний вызов print() выведет на экран такое:
('Никифоров Дмитрий Анатольевич', 'Москва', '929-876-54-32')
Теперь функция get_contacts сможет вернуть любое количество данных. Все они будут упакованы в один кортеж — tuple .
Что делать, если получили tuple
Разберем как работать с tuple на примере стандартной функции divmod . Она возвращает результат деления с остатком:
divmod(100, 3) # выведет (33, 1) divmod(2, 3) # выведет (0, 2)
Функция divmod возвращает кортеж из двух чисел — результата целочисленного деления и остаток от деления.
Мы можем сохранить результат в переменную:
div_tuple = divmod(100, 3) print(div_tuple) # выведет (33, 1)
Добраться до каждого из двух чисел можно по индексу:
div_tuple = divmod(100, 3) print(div_tuple[0]) # выведет 33 print(div_tuple[1]) # выведет 1
Индексы в коде [0] и [1] сильно осложняют чтение, поэтому полезно давать говорящие названия:
div_tuple = divmod(100, 3) int_division = div_tuple[0] remainder = div_tuple[1] print(int_division) # выведет 33 print(remainder) # выведет 1
Распаковка кортежа
При работе с кортежами очень часто приходится доставать все данные в отдельные переменные:
int_division = div_tuple[0] remainder = div_tuple[1]
Это встречается настолько часто, что в Python ввели упрощенную короткую запись:
(int_division, remainder) = divmod(100, 3) print(int_division) # выведет 33 print(remainder) # выведет 1
Запись похожа на создание кортежа - те же скобки и запятые, но работает это в обратную сторону. Называется “распаковкой”.
Если в кортеже больше одного элемента, то скобки указывать необязательно. Python любит чистый код:
int_division, remainder = divmod(100, 3) print(int_division) # выведет 33 print(remainder) # выведет 1
Последняя форма записи распаковки наиболее распространена и рекомендуется к использованию.
Скобки не обязательно указывать и при создании кортежа, но этот прием может усложнить чтение кода, будьте с ним осторожны:
contacts = full_name, city, phone_number
В коде внутри функций часто встречается еще более короткая запись:
return full_name, city, phone_number
Вызов return сообщает интерпретатору Python, что функция завершает свою работу и хочет вернуть результат. А все перечисленное справо от return будет упаковано в кортеж — tuple .
Как добавить элемент в кортеж
Добавить в кортеж ничего нельзя. Он неизменяемый, однажды созданный кортеж никак нельзя изменить. Зато можно создать новый:
old_tuple = (1, 2) new_tuple = old_tuple + (3, 4) print(new_tuple) # Выведется (1, 2, 3, 4)
Если вы хотите добавить только один элемент, то велик соблазн написать так:
old_tuple = (1, 2) new_tuple = old_tuple + 3
TypeError: can only concatenate tuple (not "int") to tuple
Эта ошибка значит, что вы попытались сложить кортеж и число, а Python умеет складывать только кортежи. Поэтому придётся сделать из вашего элемента кортеж, но с одним элементом внутри:
old_tuple = (1, 2) new_tuple = old_tuple + (3,) print(new_tuple) # Выведется (1, 2, 3)
Что ещё почитать
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.
Кортежи
Кортежи (tuple) в Python – это те же списки за одним исключением. Кортежи неизменяемые структуры данных. Так же как списки они могут состоять из элементов разных типов, перечисленных через запятую. Кортежи заключаются в круглые, а не квадратные скобки.
>>> a = (10, 2.13, "square", 89, 'C') >>> a (10, 2.13, 'square', 89, 'C')
Из кортежа можно извлекать элементы и брать срезы:
>>> a[3] 89 >>> a[1:3] (2.13, 'square')
Однако изменять его элементы нельзя:
>>> a[0] = 11 Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment
Также у типа tuple нет методов для добавления и удаления элементов.
Возникает резонный вопрос. Зачем в язык программирования был введен этот тип данных, по-сути представляющий собой неизменяемый список? Дело в том, что иногда надо защитить список от изменений. Преобразовать же кортеж в список, если это потребуется, как и выполнить обратную операцию легко с помощью встроенных в Python функций list() и tuple() :
>>> a = (10, 2.13, "square", 89, 'C') >>> b = [1, 2, 3] >>> c = list(a) >>> d = tuple(b) >>> c [10, 2.13, 'square', 89, 'C'] >>> d (1, 2, 3)
Рассмотрим случай, когда уместно использовать кортежи. В Python изменяемые объекты передаются в функцию по ссылке. Это значит, что не создается копия объекта, а переменной-параметру присваивается ссылка на уже существующий объект. В итоге, если в теле функции объект изменяется, то эти изменения касаются глобального объекта.
def add_num(seq, num): for i in range(len(seq)): seq[i] += num return seq origin = [3, 6, 2, 6] changed = add_num(origin, 3) print(origin) print(changed)
Данная программа неправильная. Хотя никаких выбросов исключений не произойдет, она содержит логическую ошибку. На выводе получаем:
[6, 9, 5, 9] [6, 9, 5, 9]
То есть исходный список был также изменен. Параметр seq содержал ссылку не на свой локальный список, а на список-оригинал. Таким образом, в операторе return здесь нет смыла. Если функция замысливалась как изменяющая глобальный список, то программа должна выглядеть так:
def add_num(seq, num): for i in range(len(seq)): seq[i] += num origin = [3, 6, 2, 6] add_num(origin, 3) print(origin)
Что делать, если все же требуется не изменять исходный список, а сформировать по нему новый. Задачу можно решить несколькими способами. Во первых, в функции можно создать локальный список, после чего возвращать его:
def add_num(seq, num): new_seq = [] for i in seq: new_seq.append(i + num) return new_seq origin = [3, 6, 2, 6] changed = add_num(origin, 3) print(origin) print(changed)
[3, 6, 2, 6] [6, 9, 5, 9]
Исходный список в функции не меняется. Его элементы лишь перебираются.
Второй способ защитить список-оригинал – использовать кортеж. Этот способ более надежный, так как в больших программах трудно отследить, что ни одна функция не содержит команд изменения глобальных данных.
Хотя преобразовывать к кортежу можно как при передаче в функцию, так и в самой функции, лучше сразу делать глобальный список кортежем. Поскольку неизменяемые объекты передаются по значению, а не по ссылке, то в функцию будет поступать копия структуры, а не оригинал. Даже если туда передается оригинал, изменить его невозможно. Можно лишь, как вариант, скопировать его и/или изменить тип, создав тем самым локальную структуру, и делать с ней все, что заблагорассудится.
def add_num(seq, num): seq = list(seq) for i in range(len(seq)): seq[i] += num return seq origin = (3, 6, 2, 6) changed = add_num(origin, 3) print(origin) print(changed)
Списки в кортежах
Кортежи могут содержать списки, также как списки быть вложенными в другие списки.
>>> nested = (1, "do", ["param", 10, 20])
Как вы думаете, можем ли мы изменить список ["param", 10, 20] вложенный в кортеж nested ? Список изменяем, кортеж – нет. Если вам кажется, что нельзя, то вам кажется неправильно. На самом деле можно:
>>> nested[2][1] = 15 >>> nested (1, 'do', ['param', 15, 20])
Примечание. Выражения типа nested[2][1] используются для обращения к вложенным объектам. Первый индекс указывает на позицию вложенного объекта, второй – индекс элемента внутри вложенного объекта. Так в данном случае сам список внутри кортежа имеет индекс 2, а элемент списка 10 – индекс 1 в списке.
Странная ситуация. Кортеж неизменяем, но мы все-таки можем изменить его. На самом деле кортеж остается неизменяемым. Просто в нем содержится не сам список, а ссылка на него. Ее изменить нельзя. Но менять сам список можно.
Чтобы было проще понять, перепишем кортеж так:
>>> l = ["param", 10, 20] >>> t = (1, "do", l) >>> t (1, 'do', ['param', 10, 20])
Кортеж содержит переменную-ссылку. Поменять ее на другую ссылку нельзя. Но кортеж не содержит самого списка. Поэтому его можно менять как угодно:
>>> l.pop(0) 'param' >>> t (1, 'do', [10, 20])
Однако такой номер не проходит с неизменяемыми типами:
>>> a = "Kat" >>> t = (a, l) >>> t ('Kat', [10, 20]) >>> a = "Bat" >>> t ('Kat', [10, 20])
Они передаются в кортеж как и в функцию – по значению. То есть их значение копируется в момент передачи.
Практическая работа
- Чтобы избежать изменения исходного списка, не обязательно использовать кортеж. Можно создать его копию с помощью метода списка copy() или взять срез от начала до конца [:] . Скопируйте список первым и вторым способом и убедитесь, что изменение копий никак не отражается на оригинале.
- Заполните один кортеж десятью случайными целыми числами от 0 до 5 включительно. Также заполните второй кортеж числами от -5 до 0. Для заполнения кортежей числами напишите одну функцию. Объедините два кортежа с помощью оператора +, создав тем самым третий кортеж. С помощью метода кортежа count() определите в нем количество нулей. Выведите на экран третий кортеж и количество нулей в нем.
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
