Справочник по Python · модуль 3 · списки и циклы
Глава 3.1
Коллекции в Python
Коллекция хранит группу значений под одним именем. Выбор между списком, кортежем, множеством и словарём зависит от того, важны ли порядок, изменение, уникальность и обращение по ключу.
- Категория
- Структуры данных
- Уровень
- Начальный
- Связанные темы
- Типы данных, for, индексы
- Зачем это знать
- Хранить и обрабатывать группы значений
§1Зачем нужны коллекции
Пока значений два-три, хватает обычных переменных. Но задача «сохранить температуру за неделю» на отдельных переменных выглядит так:
temperature_1 = 18 temperature_2 = 21 temperature_3 = 17 # ...и так далее
Такой код невозможно обработать циклом, нельзя посчитать среднее одной строкой и нельзя расширить до тридцати дней, не переписав всю программу. Коллекция решает это одним именем:
temperatures = [18, 21, 17, 23] print(sum(temperatures)) print(max(temperatures))
79 23
Количество значений при этом больше не влияет на длину кода: те же две строки работают и для четырёх, и для тысячи измерений.
§2Что такое коллекция
Коллекция — структура для хранения нескольких элементов. С коллекцией можно добавлять и удалять значения, искать их, изменять и перебирать циклом — конкретные возможности зависят от её типа.
одно значение: temperature = 18 группа значений: temperatures = [18, 21, 17, 23]
Имя коллекции по традиции ставят во множественное число: temperatures, names, prices. Это сразу подсказывает читателю кода, что внутри не одно значение.
§3Четыре основных вида
| Тип | Запись | Главная особенность |
|---|---|---|
list | [10, 20, 30] | упорядоченный изменяемый список |
tuple | (10, 20, 30) | упорядоченная неизменяемая последовательность |
set | {10, 20, 30} | неупорядоченный набор уникальных элементов |
dict | {"name": "Alex"} | пары «ключ — значение» |
Скобки различаются: квадратные у списка, круглые у кортежа, фигурные у множества и словаря. Дополнительные структуры, например deque и namedtuple, находятся в стандартной библиотеке и изучаются после основных коллекций.
Основной инструмент начинающего — список. Дальше в главе разбирается прежде всего он.
§4Список и индексы
Список — упорядоченная изменяемая коллекция. Каждый элемент занимает позицию с числовым индексом, а первый индекс равен нулю.
numbers = [10, 20, 30, 40] индекс: 0 1 2 3
Индекс — это не номер по счёту, а смещение от начала. Поэтому третий по счёту элемент лежит под индексом 2.
numbers = [10, 20, 30, 40] print(numbers[0]) print(numbers[2])
10 30
Последний допустимый индекс всегда на единицу меньше количества элементов. Обращение к numbers[4] здесь вызовет IndexError.
§5Отрицательные индексы
Python умеет отсчитывать позиции с конца. Индекс -1 означает последний элемент, -2 — предпоследний.
letters = [ "a", "b", "c", "d" ] слева: 0 1 2 3 справа: -4 -3 -2 -1
letters = ["a", "b", "c", "d"] print(letters[-1]) print(letters[-2])
d c
Это избавляет от вычислений вида «длина минус один» там, где нужен просто последний элемент. Нуля с минусом не существует: -0 — это тот же 0, то есть первый элемент.
§6len(): длина коллекции
len() — встроенная функция, которая возвращает количество элементов. Она понадобится почти в каждой задаче с коллекциями.
temperatures = [18, 21, 17, 23] print(len(temperatures)) print(temperatures[len(temperatures) - 1])
4 23
У пустого списка [] длина равна 0, и обращаться по любому индексу к нему нельзя. Проверка if len(items) > 0 — стандартный способ убедиться, что данные вообще есть.
§7Изменение списка
Элемент списка можно заменить по индексу. Сам список после этого остаётся той же коллекцией, но его содержимое меняется.
numbers = [10, 20, 30] numbers[1] = 50 print(numbers)
[10, 50, 30]
Слева от знака = запись numbers[1] означает не «взять значение», а «указать ячейку для записи». Подробно этот механизм разбирается в главе 3.6.
§8Перебор циклом
Главная причина складывать данные в коллекцию — возможность обработать их одним циклом, независимо от количества. Сам цикл подробно разбирается в главах 3.2–3.4; здесь достаточно увидеть, ради чего он нужен.
temperatures = [18, 21, 17, 23] for temperature in temperatures: print(temperature)
18 21 17 23
Переменная цикла получает значение очередного элемента. Имя для неё берут в единственном числе — temperature при списке temperatures, — и код читается как фраза: «для каждой температуры из температур».
Если нужны не значения, а позиции, используют форму for index in range(len(items)) — ей посвящена глава 3.6.
§9Порядок и доступ
| Коллекция | Порядок | Как обращаются к элементу |
|---|---|---|
list, tuple, str | позиции идут последовательно | по числовому индексу |
dict | сохраняет порядок добавления | по ключу, а не по позиции |
set | порядок не предназначен для позиционного доступа | обычного индекса нет |
У словаря порядок добавления сохраняется, но запись dictionary[0] означает поиск ключа 0, а не первого элемента. У множества индексов нет вовсе: {1, 2, 3}[0] вызовет TypeError.
§10Изменяемость
Изменяемые коллекции можно обновлять после создания. Неизменяемые нельзя менять по частям — для другого содержимого создают новый объект.
| Изменяемые | Неизменяемые |
|---|---|
list, dict, set, deque | tuple, str, frozenset |
point = (10, 20) print(point[0]) # point[0] = 5 → TypeError
10
Неизменяемость — не ограничение, а гарантия. Кортеж уместен там, где данные не должны меняться случайно: координаты точки, дата, пара «широта и долгота».
§11Разные типы элементов
Список может хранить значения разных типов одновременно.
data = [10, "Python", True, 3.14] print(data)
[10, 'Python', True, 3.14]
Это допустимо, но однородный список обычно проще обрабатывать: все температуры или все имена можно передать в sum() или отсортировать, а смешанный — нет.
Исключение — записи, где позиции имеют разный смысл: ["Иванов", 17, True]. Для таких данных обычно лучше подходят словарь или кортеж.
§12Вложенные коллекции
Элементом списка может быть другая коллекция. Так представляют таблицы и составные записи.
matrix = [
[1, 2],
[3, 4]
]
print(len(matrix))
print(matrix[1])
2 [3, 4]
Длина внешнего списка равна 2: в нём лежат не четыре числа, а два списка. Запись matrix[1] даёт целую строку таблицы.
Чтобы добраться до конкретного числа, к результату применяют индекс ещё раз. Двойные скобки читаются слева направо:
matrix[1][0]
│ └ ② из полученного списка [3, 4] взять элемент 0 → 3
└ ① из matrix взять элемент 1 → [3, 4]
row = matrix[1] print(row[0]) print(matrix[1][0])
3 3
Первый индекс выбирает строку, второй — позицию внутри неё. Такой порядок сохраняется и на большей глубине вложенности.
§13Строка как последовательность
Строка тоже упорядоченная коллекция — из символов. К ней применимы индексы, отрицательные индексы, len() и перебор циклом.
word = "Python" print(word[0]) print(word[-1]) print(len(word))
P n 6
Отличие одно, но важное: строка неизменяема. Запись word[0] = "J" вызовет TypeError — вместо изменения создают новую строку.
§14Как выбрать коллекцию
| Что нужно | Подходящий тип |
|---|---|
| хранить значения по порядку и менять их | list |
| защитить набор от изменений | tuple |
| убрать повторы, быстро проверять наличие | set |
| находить значение по имени или коду | dict |
При сомнениях начинают со списка: он покрывает большинство учебных задач, а перейти к другому типу можно позже.
§15Частые ошибки
| Что написано | Что произойдёт | Как правильно |
|---|---|---|
numbers[1] называют первым элементом | будет взят второй элемент | помнить, что первый индекс равен 0 |
numbers[4] для списка из четырёх элементов | IndexError | использовать индексы от 0 до 3 |
numbers[len(numbers)] | IndexError: длина на единицу больше последнего индекса | numbers[len(numbers) - 1] или numbers[-1] |
point[0] = 5 для кортежа | TypeError: кортеж неизменяем | создать новый кортеж или выбрать список |
numbers.len() | AttributeError: это функция, а не метод | len(numbers) |
matrix[1, 0] для вложенного списка | TypeError | matrix[1][0] |
| ожидать постоянный порядок множества | вывод может идти не в порядке добавления | не использовать set для позиционных данных |
{} считают пустым множеством | создастся пустой словарь | для пустого множества писать set() |
§16Проверьте себя
Как получить первый элемент списка items?
items[0], потому что индексация начинается с нуля.
Как получить последний элемент, не зная длины?
items[-1]. Отрицательные индексы отсчитывают позиции с конца.
Чему равна len(matrix) для [[1, 2], [3, 4]]?
2: во внешнем списке два элемента, и каждый из них — список.
Что означает запись matrix[1][0]?
Сначала из matrix берётся элемент с индексом 1, а затем из полученного списка — элемент с индексом 0.
Какая коллекция хранит только уникальные элементы?
Множество set.
Можно ли заменить элемент кортежа по индексу?
Нет. Кортеж неизменяем; для другого содержимого нужно создать новый кортеж.
§17Шпаргалка
[1, 2, 3](1, 2, 3){1, 2, 3}{"key": "value"}items[0]items[-1]len(items)matrix[1][0]for item in items:Итог главы
Коллекции хранят группы данных под одним именем и потому позволяют обрабатывать любое количество значений одним циклом. Список изменяем и поддерживает доступ по позиции, кортеж неизменяем, множество хранит уникальные элементы, а словарь связывает ключи со значениями. Индексы начинаются с нуля, отрицательные отсчитывают с конца, а len() даёт количество элементов.