Перейти к основному содержимому

5.02. Коллекции

Разработчику Архитектору

Коллекции

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

Последовательности — это упорядоченные коллекции элементов, доступные по индексу. К ним относятся строки (str), списки (list), кортежи (tuple), а также объекты range, bytes и другие. Все последовательности поддерживают общие операции: индексирование, срезы, конкатенацию, повторение и проверку на вхождение.

Базовые операции:

  • Индексирование: seq[i] — получение элемента по индексу (от 0).
  • Срезы: seq[start:stop:step] — извлечение подпоследовательности.
  • Длина: len(seq) — количество элементов.
  • Принадлежность: x in seq — возвращает True, если x содержится в последовательности.
  • Конкатенация: seq1 + seq2 — объединение (если типы совместимы).
  • Повторение: seq * n — повторение последовательности n раз.
s = "hello"
print(s[1]) # 'e'
print(s[1:4]) # 'ell'
print('h' in s) # True
print(s * 2) # 'hellohello'

lst = [1, 2, 3]
print(lst + [4, 5]) # [1, 2, 3, 4, 5]

Циклы for естественно работают с последовательностями:

for item in [10, 20, 30]:
print(item)

Особенность строк — неизменяемость.

При попытке модификации через индекс возникнет TypeError. Для списков и кортежей это ограничение действует только для кортежей (они тоже неизменяемы). Но, собственно, давайте по порядку.

Коллекции — это типы данных, предназначенные для хранения упорядоченных или неупорядоченных множеств элементов. В языке Python коллекции реализованы как встроенные классы (встроенные типы), обеспечивающие различные семантики доступа, модификации и организации данных.

Основные встроенные коллекции включают:

  • list — список;
  • tuple — кортеж;
  • set — множество;
  • dict — словарь.

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

Списки (list).

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

Создание:

lst = [1, 2, 3]

Индексация и срезы.

Доступ к элементам осуществляется по индексу:

lst[0]      # первый элемент
lst[-1] # последний элемент

Срезы позволяют извлекать подпоследовательности:

lst[1:3]    # элементы с индексами 1 и 2
lst[::2] # каждый второй элемент

Срезы возвращают новый объект list. Они поддерживают шаг, отрицательные индексы и обратный порядок.

Списки имеют следующие методы:

  • append(x) - Добавляет элемент x в конец списка.
  • extend(iterable) - Добавляет все элементы итерируемого объекта в конец.
  • insert(i, x) - Вставляет элемент x на позицию i.
  • remove(x) - Удаляет первое вхождение элемента x.
  • pop([i]) - Удаляет и возвращает элемент по индексу (по умолчанию — последний).
  • count(x) - Возвращает количество вхождений элемента x.
  • sort(key=None, reverse=False) - Сортирует список in-place.
  • reverse() - Переворачивает список in-place.
  • copy() - Создаёт поверхностную копию списка.

Примечание: методы sort и reverse модифицируют исходный объект и возвращают None.

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

Бинарные списки: array.array используются для эффективного хранения числовых данных большого объёма. Этот тип представляет собой массив примитивных значений (например, целых или вещественных чисел) фиксированного размера.

import array
arr = array.array('i', [1, 2, 3]) # массив 32-битных целых

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

Кортежи (tuple)

Кортеж — это упорядоченная, неизменяемая коллекция элементов произвольных типов. После создания кортеж нельзя модифицировать: нельзя добавлять, удалять или заменять элементы. Кортежи неизменяемые (чтобы гарантировать целостность данных), хэшируемые (сам кортеж может использовать в качестве ключа в словаре или элементе множества), производительны и применяются часто для представления составных данных, например, координат (x, y) или возврат нескольких значений из функции.

Пример:

t = (1, 2, 3)
t = 1, 2, 3 # скобки опциональны

Кортежи поддерживают ограниченный набор методов:

  • count(x) — количество вхождений элемента x.
  • index(x[, start[, end]]) — индекс первого вхождения x.

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

Множества (set)

Множество — это неупорядоченная, изменяемая коллекция уникальных элементов. Элементы множества должны быть хэшируемыми (т.е. иметь метод __hash__ и быть сравнимыми).

Создание:

s = {1, 2, 3}
s = set([1, 2, 3]) # из итерируемого

Пустое множество создаётся только через set(), так как {} интерпретируется как пустой словарь.

Множества автоматически устраняют дубликаты:

{1, 1, 2}  # → {1, 2}

Множества бывают изменяемыми и неизменяемыми.

Методы изменяемых множеств (set):

  • add(x) — добавить элемент.
  • remove(x) — удалить элемент; ошибка, если нет.
  • discard(x) — удалить, если есть; ошибки не возникает.
  • pop() — удалить и вернуть произвольный элемент.
  • clear() — очистить множество.

frozenset — неизменяемая версия множества. Поддерживает все операции чтения и теоретико-множественные операции, но не позволяет модифицировать содержимое. Полезен как ключ в словаре или элемент другого множества.

Словари (dict)

Словарь — это изменяемая коллекция пар «ключ-значение», где ключи уникальны и хэшируемы, а значения могут быть любыми объектами. Доступ к значениям осуществляется по ключу. Словари реализованы как хеш-таблицы с открытой адресацией.

Создание:

d = {'a': 1, 'b': 2}
d = dict(a=1, b=2)

Ключи должны быть хэшируемыми (числа, строки, кортежи из хэшируемых объектов и т.д.). Значения же произвольные объекты, включая изменяемые. Словари сохраняют порядок вставки с Python 3.7+ (в 3.6 — как особенность CPython, с 3.7 — как гарантия языка).

Методы словарей:

  • keys() - Итератор ключей;
  • values() - Итератор значений;
  • items() - Итератор пар (ключ, значение);
  • get(key, default=None) - Значение по ключу или значение по умолчанию;
  • pop(key, default) - Удаляет и возвращает значение; если ключа нет — возвращает default;
  • update(other) - Обновляет словарь парами из другого словаря или итерируемого;
  • setdefault(key, default) - Возвращает значение, если ключ есть; иначе устанавливает и возвращает default;
  • clear() - Очищает словарь;
  • copy() - Поверхностная копия.