Списки и кортежи в Python

27 мая, 2020

Подписывайся на наш канал в Telegram, чтобы ежедневно совершенствоваться в Python. Там выходят задачи, полезные советы и сливы платных курсов - перейти

Оглавление

  • Списки Python
    • Списки заказаны
    • Списки могут содержать произвольные объекты
    • Элементы списка могут быть доступны по индексу
    • Списки могут быть вложенными
    • Списки изменяемы
    • Списки динамичны
  • Python кортежи
    • Определение и использование кортежей
    • Назначение, упаковка и распаковка кортежей
  • Вывод

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

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

Списки Python

Короче говоря, список – это набор произвольных объектов, несколько похожий на массив во многих других языках программирования, но более гибкий. Списки определяются в Python путем заключения в квадратные скобки ([]) разделенных запятыми последовательностей объектов , как показано ниже:

>>> a = ['foo', 'bar', 'baz', 'qux']

>>> print(a)
['foo', 'bar', 'baz', 'qux']
>>> a
['foo', 'bar', 'baz', 'qux']

Важными характеристиками списков Python являются следующие:

  • Списки упорядочены.
  • Списки могут содержать любые произвольные объекты.
  • Элементы списка могут быть доступны по индексу.
  • Списки могут быть вложены на произвольную глубину.
  • Списки изменчивы.
  • Списки являются динамическими.

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

Списки упорядочены

Список – это не просто набор объектов. Это упорядоченная коллекция предметов. Порядок, в котором вы указываете элементы при определении списка, является врожденной характеристикой этого списка и поддерживается в течение всего срока существования этого списка. (Вы увидите тип данных Python, который не упорядочен в следующем уроке по словарям.)

Списки с одинаковыми элементами в другом порядке не совпадают:

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> b = ['baz', 'qux', 'bar', 'foo']
>>> a == b
False
>>> a is b
False

>>> [1, 2, 3, 4] == [4, 1, 3, 2]
False

Списки могут содержать произвольные объекты

Список может содержать любой ассортимент объектов. Элементы списка могут быть одного типа:

>>> a = [2, 4, 6, 8]
>>> a
[2, 4, 6, 8]

Или элементы могут быть разных типов:

>>> a = [21.42, 'foobar', 3, 4, 'bark', False, 3.14159]
>>> a
[21.42, 'foobar', 3, 4, 'bark', False, 3.14159]

Списки могут даже содержать сложные объекты, такие как функции, классы и модули:

>>> int
<class 'int'>
>>> len
<built-in function len>
>>> def foo():
...     pass
...
>>> foo
<function foo at 0x035B9030>
>>> import math
>>> math
<module 'math' (built-in)>

>>> a = [int, len, foo, math]
>>> a
[<class 'int'>, <built-in function len>, <function foo at 0x02CA2618>,
<module 'math' (built-in)>]

Список может содержать любое количество объектов, от нуля до такого количества, которое позволяет память вашего компьютера:

>>> a = []
>>> a
[]

>>> a = [ 'foo' ]
>>> a
['foo']

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
... 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
... 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
... 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
... 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99, 100]

(Список с одним объектом иногда называют одноэлементным списком.)

Объекты списка не обязательно должны быть уникальными. Данный объект может появляться в списке несколько раз:

>>> a = ['bark', 'meow', 'woof', 'bark', 'cheep', 'bark']
>>> a
['bark', 'meow', 'woof', 'bark', 'cheep', 'bark']

Элементы списка могут быть доступны по индексу

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

Рассмотрим следующий список:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

Индексы для элементов в a показаны ниже:

Схема списка Python
Список индексов

Вот код Python для доступа к некоторым элементам a:

>>> a[0]
'foo'
>>> a[2]
'baz'
>>> a[5]
'corge'

Практически все, что касается индексации строк, работает аналогично для списков. Например, отрицательный индекс списка отсчитывается с конца списка:

Схема списка Python
Индексирование отрицательного списка
>>> a[-1]
'corge'
>>> a[-2]
'quux'
>>> a[-5]
'bar'

Нарезка тоже работает. Если a это список, выражение a[m:n] возвращает часть из a , от m до n , но не включая сам n:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a[2:5]
['baz', 'qux', 'quux']

Другие функции нарезки строк работают аналогично и для нарезки списков:

  • Можно указывать как положительные, так и отрицательные показатели:
>>> a[-5:-2]
['bar', 'baz', 'qux']
>>> a[1:4]
['bar', 'baz', 'qux']
>>> a[-5:-2] == a[1:4]
True
  • Пропуск первого индекса запускает срез в начале списка, а пропуск второго индекса расширяет срез до конца списка:
>>> print(a[:4], a[0:4])
['foo', 'bar', 'baz', 'qux'] ['foo', 'bar', 'baz', 'qux']
>>> print(a[2:], a[2:len(a)])
['baz', 'qux', 'quux', 'corge'] ['baz', 'qux', 'quux', 'corge']

>>> a[:4] + a[4:]
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[:4] + a[4:] == a
True
  • Вы можете указать шаг – положительный или отрицательный:
>>> a[0:6:2]
['foo', 'baz', 'quux']
>>> a[1:6:2]
['bar', 'qux', 'corge']
>>> a[6:0:-2]
['corge', 'qux', 'bar']
  • Синтаксис для обращения к списку работает так же, как и для строк:
>>> a[::-1]
['corge', 'quux', 'qux', 'baz', 'bar', 'foo']
  • Синтаксис[:] работает для списков. Однако есть важное различие между тем, как эта операция работает со списком, и тем, как она работает со строкой. Если s это строка, s[:] возвращает ссылку на тот же объект:
>>> s = 'foobar'
>>> s[:]
'foobar'
>>> s[:] is s
True
  • И наоборот, если a это список, a[:] возвращает новый объект, который является копией
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[:]
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[:] is a
False

Несколько операторов Python и встроенных функций также могут использоваться со списками, аналогичным строкам способами:

  • Операторы in и not in:
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> 'qux' in a
True
>>> 'thud' not in a
True
  • Операторы конкатенации (+) и репликации (*):
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a + ['grault', 'garply']
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 'grault', 'garply']
>>> a * 2
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 'foo', 'bar', 'baz',
'qux', 'quux', 'corge']
  • Функции len()min() и max():
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> len(a)
6
>>> min(a)
'bar'
>>> max(a)
'qux'

Не случайно строки и списки ведут себя одинаково. Оба они являются частными случаями более общего типа объекта, называемого итерируемым.

Кстати, в каждом приведенном выше примере список всегда присваивается переменной до того, как над ней выполняется какая-либо операция. Но вы также можете оперировать литералом списка:

>>> ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'][2]
'baz'

>>> ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'][::-1]
['corge', 'quux', 'qux', 'baz', 'bar', 'foo']

>>> 'quux' in ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
True

>>> ['foo', 'bar', 'baz'] + ['qux', 'quux', 'corge']
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> len(['foo', 'bar', 'baz', 'qux', 'quux', 'corge'][::-1])
6

В этом отношении вы можете сделать то же самое со строковым литералом:

>>> 'If Comrade Napoleon says it, it must be right.'[::-1]
'.thgir eb tsum ti ,ti syas noelopaN edarmoC fI'

Списки могут быть вложенными

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

Посмотрите на этот (по общему мнению, надуманный) пример:

>>> x = ['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
>>> x
['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']

Структура объекта, на которую xссылаются, представлена ​​ниже:

Диаграмма вложенных списков
Вложенный список

x[0]x[2] и x[4] являются строками, каждая из которых имеет длину:

>>> print(x[0], x[2], x[4])
a g j

Но x[1] и x[3] – подсписки:

>>> x[1]
['bb', ['ccc', 'ddd'], 'ee', 'ff']

>>> x[3]
['hh', 'ii']

Чтобы получить доступ к элементам в подсписке, просто добавьте дополнительный индекс:

>>> x[1]
['bb', ['ccc', 'ddd'], 'ee', 'ff']

>>> x[1][0]
'bb'
>>> x[1][1]
['ccc', 'ddd']
>>> x[1][2]
'ee'
>>> x[1][3]
'ff'

>>> x[3]
['hh', 'ii']
>>> print(x[3][0], x[3][1])
hh ii

x[1][1] это еще один подсписок, поэтому добавление еще одного индекса позволяет получить доступ к его элементам:

>>> x[1][1]
['ccc', 'ddd']
>>> print(x[1][1][0], x[1][1][1])
ccc ddd

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

Весь обычный синтаксис в отношении индексов и секционирования также применим к подспискам:

>>> x[1][1][-1]
'ddd'
>>> x[1][1:3]
[['ccc', 'ddd'], 'ee']
>>> x[3][::-1]
['ii', 'hh']

Однако следует помнить, что операторы и функции применяются только к списку на указанном вами уровне и не являются рекурсивными. Рассмотрим, что происходит, когда вы запрашиваете длину x используя len():

>>> x
['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
>>> len(x)
5

>>> x[0]
'a'
>>> x[1]
['bb', ['ccc', 'ddd'], 'ee', 'ff']
>>> x[2]
'g'
>>> x[3]
['hh', 'ii']
>>> x[4]
'j'

x имеет только пять элементов – три строки и два подсписка. Отдельные элементы в подсписках не учитываются по x длине.

Вы столкнетесь с подобной ситуацией при использовании in оператора:

>>> 'ddd' in x
False
>>> 'ddd' in x[1]
False
>>> 'ddd' in x[1][1]
True

'ddd' не является одним из элементов в x или x[1]. Это только непосредственно элемент в подсписке x[1][1]. Отдельный элемент в подсписке не считается элементом родительского списка(ов).

Списки изменяемы

Большинство типов данных, с которыми вы возможно столкнулись до этого, были атомарными.  Integer или float объекты, например, являются примитивными единицами, которые не могут быть далее разбиты. Эти типы являются неизменяемыми, что означает, что они не могут быть изменены после назначения. Не имеет смысла думать об изменении значения целого числа. Если вы хотите другое целое число, вы просто назначаете другое.

Напротив, string тип является составным типом. Строки сводятся к меньшим частям – компонентам символов. Возможно, имеет смысл подумать об изменении символов в строке. Но вы не можете. В Python строки также неизменны.

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

Изменение значения одного списка

Одно значение в списке можно заменить индексированием и простым присваиванием:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a[2] = 10
>>> a[-1] = 20
>>> a
['foo', 'bar', 10, 'qux', 'quux', 20]

Вы не можете сделать это со строкой:

>>> s = 'foobarbaz'
>>> s[2] = 'x'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Элемент списка можно удалить с помощью del команды:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> del a[3]
>>> a
['foo', 'bar', 'baz', 'quux', 'corge']

Изменение нескольких значений списка

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

a[m:n] = <iterable>

Опять же, на данный момент, подумайте о повторяемости как список. Это назначение заменяет указанный фрагмент a с <iterable>:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a[1:4]
['bar', 'baz', 'qux']
>>> a[1:4] = [1.1, 2.2, 3.3, 4.4, 5.5]
>>> a
['foo', 1.1, 2.2, 3.3, 4.4, 5.5, 'quux', 'corge']
>>> a[1:6]
[1.1, 2.2, 3.3, 4.4, 5.5]
>>> a[1:6] = ['Bark!']
>>> a
['foo', 'Bark!', 'quux', 'corge']

Количество вставленных элементов не обязательно должно быть равно количеству замененных. Python просто увеличивает или сокращает список по мере необходимости.

Вы можете вставить несколько элементов вместо одного элемента – просто используйте фрагмент, который обозначает только один элемент:

>>> a = [1, 2, 3]
>>> a[1:2] = [2.1, 2.2, 2.3]
>>> a
[1, 2.1, 2.2, 2.3, 3]

Обратите внимание, что это не то же самое, что замена одного элемента списком:

>>> a = [1, 2, 3]
>>> a[1] = [2.1, 2.2, 2.3]
>>> a
[1, [2.1, 2.2, 2.3], 3]

Вы также можете вставлять элементы в список, не удаляя ничего. Просто укажите срез формы [n:n] (срез нулевой длины) с нужным индексом:

>>> a = [1, 2, 7, 8]
>>> a[2:2] = [3, 4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8]

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

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[1:5] = []
>>> a
['foo', 'corge']

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> del a[1:5]
>>> a
['foo', 'corge']

Ожидание или добавление элементов в список

Дополнительные элементы могут быть добавлены в начало или конец списка с помощью + оператора конкатенации или оператора += расширенного присваивания:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a += ['grault', 'garply']
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 'grault', 'garply']

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a = [10, 20] + a
>>> a
[10, 20, 'foo', 'bar', 'baz', 'qux', 'quux', 'corge']

Обратите внимание, что список должен быть объединен с другим списком, поэтому, если вы хотите добавить только один элемент, вам нужно указать его как одноэлементный список:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a += 20
Traceback (most recent call last):
  File "<pyshell#58>", line 1, in <module>
    a += 20
TypeError: 'int' object is not iterable

>>> a += [20]
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 20]

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

Строки также итеративны. Но посмотрите, что происходит, когда вы объединяете строку в список:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux']
>>> a += 'corge'
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'c', 'o', 'r', 'g', 'e']

Этот результат, возможно, не совсем то, что вы ожидали. Когда строка проходит итерацию, результатом является список ее компонентов. В приведенном выше примере в список добавляется список a символов в строке 'corge'.

Если вы действительно хотите добавить только одну строку 'corge'в конец списка, вам нужно указать ее как одноэлементный список:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux']
>>> a += ['corge']
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

Методы, которые изменяют список

Наконец, Python предоставляет несколько встроенных методов, которые можно использовать для изменения списков. Информация об этих методах подробно описана ниже.

Примечание . Строковые методы, не изменяют целевую строку напрямую. Это потому, что строки неизменны. Вместо этого строковые методы возвращают новый строковый объект, который изменяется в соответствии с указаниями метода. Они оставляют исходную целевую строку без изменений:

>>> s = 'foobar'
>>> t = s.upper()
>>> print(s, t)
foobar FOOBAR

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

a.append(<obj>) – Добавляет объект в список.

a.append(<obj>) добавляет объект <obj> в конец списка a:

>>> a = ['a', 'b']
>>> a.append(123)
>>> a
['a', 'b', 123]

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

>>> a = ['a', 'b']
>>> x = a.append(123)
>>> print(x)
None
>>> a
['a', 'b', 123]

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

>>> a = ['a', 'b']
>>> a + [1, 2, 3]
['a', 'b', 1, 2, 3]

Метод .append() не работает таким образом! Если итератор добавляется в список с помощью .append(), он добавляется как один объект:

>>> a = ['a', 'b']
>>> a.append([1, 2, 3])
>>> a
['a', 'b', [1, 2, 3]]
>>> a = ['a', 'b']
>>> a.append('foo')
>>> a
['a', 'b', 'foo']

a.extend(<iterable>) – Расширяет список объектов из итерируемого.

Да, это вероятно то, что вы думаете. .extend() также добавляет в конец списка, но ожидается, что аргумент будет повторяемым. Элементы <iterable> добавляются индивидуально:

>>> a = ['a', 'b']
>>> a.extend([1, 2, 3])
>>> a
['a', 'b', 1, 2, 3]

Другими словами, .extend() ведет себя как + оператор. Точнее, поскольку он изменяет список на месте, он ведет себя как += оператор:

>>> a = ['a', 'b']
>>> a += [1, 2, 3]
>>> a
['a', 'b', 1, 2, 3]

a.insert(<index>, <obj>) – Вставляет объект в список.

a.insert(<index>, <obj>) вставляет объект <obj> в список a по указанному <index>. После вызова метода, a[<index>] является <obj> и остальные элементы списка сдвигаются вправо:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a.insert(3, 3.14159)
>>> a[3]
3.14159
>>> a
['foo', 'bar', 'baz', 3.14159, 'qux', 'quux', 'corge']

a.remove(<obj>) – Удаляет объект из списка.

a.remove(<obj>) удаляет объект <obj> из списка a. Если <obj> не в a, возникает исключение:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a.remove('baz')
>>> a
['foo', 'bar', 'qux', 'quux', 'corge']

>>> a.remove('Bark!')
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a.remove('Bark!')
ValueError: list.remove(x): x not in list

a.pop(index=-1) – удаляет элемент из списка.

Этот метод отличается от .remove():

  1. Вы указываете индекс удаляемого элемента, а не сам объект.
  2. Метод возвращает значение: элемент, который был удален.

a.pop() просто удаляет последний элемент в списке:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a.pop()
'corge'
>>> a
['foo', 'bar', 'baz', 'qux', 'quux']

>>> a.pop()
'quux'
>>> a
['foo', 'bar', 'baz', 'qux']

Если указан необязательный параметр <index> , элемент по этому индексу удаляется и возвращается. <index> может быть отрицательным, как при индексировании строк и списков:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a.pop(1)
'bar'
>>> a
['foo', 'baz', 'qux', 'quux', 'corge']

>>> a.pop(-3)
'qux'
>>> a
['foo', 'baz', 'quux', 'corge']

<index> по умолчанию -1, поэтому a.pop(-1) эквивалентно a.pop().

Списки динамичны

Этот урок начался со списка из шести определяющих характеристик списков Python. Последнее – списки являются динамическими. Вы видели много примеров этого в разделах выше. Когда элементы добавляются в список, он увеличивается по мере необходимости:

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

>>> a[2:2] = [1, 2, 3]
>>> a += [3.14159]
>>> a
['foo', 'bar', 1, 2, 3, 'baz', 'qux', 'quux', 'corge', 3.14159]

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

>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[2:3] = []
>>> del a[0]
>>> a
['bar', 'qux', 'quux', 'corge']

Python кортежи

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

Определение и использование кортежей

Кортежи идентичны спискам во всех отношениях, за исключением следующих свойств:

  • Кортежи определяются заключением элементов в круглые скобки (()) вместо квадратных скобок ([]).
  • Кортежи неизменны.

Вот короткий пример, показывающий определение кортежа, индексацию и нарезку:

>>> t = ('foo', 'bar', 'baz', 'qux', 'quux', 'corge')
>>> t
('foo', 'bar', 'baz', 'qux', 'quux', 'corge')

>>> t[0]
'foo'
>>> t[-1]
'corge'
>>> t[1::2]
('bar', 'qux', 'corge')

Не бойся! Наш любимый механизм реверсирования строк и списков работает и для кортежей:

>>> t[::-1]
('corge', 'quux', 'qux', 'baz', 'bar', 'foo')

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

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

>>> t = ('foo', 'bar', 'baz', 'qux', 'quux', 'corge')
>>> t[2] = 'Bark!'
Traceback (most recent call last):
  File "<pyshell#65>", line 1, in <module>
    t[2] = 'Bark!'
TypeError: 'tuple' object does not support item assignment

Зачем использовать кортеж вместо списка?

  • Выполнение программы быстрее при манипулировании кортежем, чем для эквивалентного списка. (Это, вероятно, не будет заметно, когда список или кортеж невелики.)
  • Иногда вы не хотите, чтобы данные были изменены. Если значения в коллекции должны оставаться постоянными в течение всего срока действия программы, использование кортежа вместо списка защищает от случайного изменения.
  • Есть еще один тип данных Python, который называется словарь, который требует в качестве одного из компонентов значение неизменяемого типа. Для этой цели можно использовать кортеж, а список – нет.

В сеансе Python REPL вы можете отображать значения нескольких объектов одновременно, вводя их непосредственно в >>> командной строке через запятую:

>>> a = 'foo'
>>> b = 42
>>> a, 3.14159, b
('foo', 3.14159, 42)

Python отображает ответ в скобках, потому что он неявно интерпретирует входные данные как кортеж.

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

>>> t = ()
>>> type(t)
<class 'tuple'>
>>> t = (1, 2)
>>> type(t)
<class 'tuple'>
>>> t = (1, 2, 3, 4, 5)
>>> type(t)
<class 'tuple'>

Но что происходит, когда вы пытаетесь определить кортеж с одним элементом:

>>> t = (2)
>>> type(t)
<class 'int'>

Поскольку круглые скобки также используются для определения приоритета оператора в выражениях, Python оценивает выражение (2) как просто целое число 2 и создает int объект. Чтобы сообщить Python, что вы действительно хотите определить одноэлементный кортеж, добавьте завершающую запятую (,) перед закрывающей скобкой:

>>> t = (2,)
>>> type(t)
<class 'tuple'>
>>> t[0]
2
>>> t[-1]
2

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

Когда вы отображаете одноэлементный кортеж, Python включает запятую, чтобы напомнить вам, что это кортеж:

>>> print(t)
(2,)

Назначение, упаковка и распаковка кортежей

Как вы уже видели выше, для одного объекта может быть назначен буквальный кортеж, содержащий несколько элементов:

>>> t = ('foo', 'bar', 'baz', 'qux')

Когда это происходит, все элементы в кортеже «упакованы» в объект:

упаковка кортежей
Упаковка кортежей
>>> t
('foo', 'bar', 'baz', 'qux')
>>> t[0]
'foo'
>>> t[-1]
'qux'

Если этот «упакованный» объект впоследствии назначается новому кортежу, отдельные элементы «распаковываются» в объекты в кортеже:

распаковка кортежей
Распаковка кортежей
>>> (s1, s2, s3, s4) = t
>>> s1
'foo'
>>> s2
'bar'
>>> s3
'baz'
>>> s4
'qux'

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

>>> (s1, s2, s3) = t
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    (s1, s2, s3) = t
ValueError: too many values to unpack (expected 3)

>>> (s1, s2, s3, s4, s5) = t
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    (s1, s2, s3, s4, s5) = t
ValueError: not enough values to unpack (expected 5, got 4)

Упаковка и распаковка могут быть объединены в один оператор для составного присваивания:

>>> (s1, s2, s3, s4) = ('foo', 'bar', 'baz', 'qux')
>>> s1
'foo'
>>> s2
'bar'
>>> s3
'baz'
>>> s4
'qux'

Опять же, количество элементов в кортеже слева от присвоения должно равняться числу справа:

>>> (s1, s2, s3, s4, s5) = ('foo', 'bar', 'baz', 'qux')
Traceback (most recent call last):
  File "<pyshell#63>", line 1, in <module>
    (s1, s2, s3, s4, s5) = ('foo', 'bar', 'baz', 'qux')
ValueError: not enough values to unpack (expected 5, got 4)

В подобных назначениях и в небольшом числе других ситуаций Python позволяет опустить скобки, которые обычно используются для обозначения кортежа:

>>> t = 1, 2, 3
>>> t
(1, 2, 3)

>>> x1, x2, x3 = t
>>> x1, x2, x3
(1, 2, 3)

>>> x1, x2, x3 = 4, 5, 6
>>> x1, x2, x3
(4, 5, 6)

>>> t = 2,
>>> t
(2,)

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

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

>>> a = 'foo'
>>> b = 'bar'
>>> a, b
('foo', 'bar')

>>># We need to define a temp variable to accomplish the swap.
>>> temp = a
>>> a = b
>>> b = temp

>>> a, b
('bar', 'foo')

В Python обмен может быть выполнен с помощью одного присваивания кортежа:

>>> a = 'foo'
>>> b = 'bar'
>>> a, b
('foo', 'bar')

>>># Magic time!
>>> a, b = b, a

>>> a, b
('bar', 'foo')

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

Вывод

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

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


Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram