Коллекции - списки, кортежи, словари, множества
Структуры данных — о разделе → реализация и псевдокод операций → Коллекции в контексте ООП.
Ниже — list, dict, set в Python.
список.append(x) # динамический массив, в конец
элемент := список[i] # O(1) по индексу
словарь[ключ] := значение # хеш-таблица, в среднем O(1)
значение := словарь[ключ]
множество.add(x) # уникальные элементы
Play ITЗагрузка интерактивного демо…
Play ITЗагрузка интерактивного демо…
Коллекции
Последовательности
Типы данных не всегда единичны, и порой их нужно перечислять в форме коллекции, собирая несколько элементов.
Последовательности — это упорядоченные коллекции элементов, доступные по индексу. К ним относятся строки (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]
Разбор:
s[1]берет символ по индексу.s[1:4]делает срез: старт включается, стоп не включается.'h' in sпроверяет вхождение подстроки.s * 2повторяет строку два раза.lst + [4, 5]создает новый список, исходныйlstостается без изменений.
Циклы for естественно работают с последовательностями:
for item in [10, 20, 30]:
print(item)
Особенность строк — неизменяемость.
При попытке модификации через индекс возникнет TypeError. Для списков и кортежей это ограничение действует только для кортежей (они тоже неизменяемы). Но, собственно, давайте по порядку.
Коллекции — это типы данных, предназначенные для хранения упорядоченных или неупорядоченных множеств элементов. В языке Python коллекции реализованы как встроенные классы (встроенные типы), обеспечивающие различные семантики доступа, модификации и организации данных.
Основные встроенные коллекции включают:
list— список;tuple— кортеж;set— множество;dict— словарь.
Каждая из этих структур отличается по четырём частым критериям выбора:
- Индексация — доступ к элементу по целочисленной позиции:
lst[0],t[1]. - Упорядоченность — при обходе элементы идут в предсказуемом порядке (как при вставке или по правилу сортировки).
- Изменяемость — можно ли после создания менять состав или значения.
- Дубликаты — допускаются ли повторяющиеся элементы (у
dictуникальны только ключи).
Сводка свойств встроенных коллекций
| Тип | Индексация по i | Упорядочен | Изменяем | Дубликаты | Литерал |
|---|---|---|---|---|---|
list | да | да | да | да | [1, 2, 3] |
tuple | да | да | нет | да | (1, 2, 3) |
set | нет | нет* | да | нет | {1, 2, 3} |
dict | по ключу** | да (с 3.7+)*** | да | ключи уникальны | {"a": 1} |
* у set порядок обхода в CPython может совпадать с порядком вставки, но на него не опираются в логике программы — тип считается неупорядоченным.
** у dict доступ d["имя"], а не d[0]; целочисленный индекс позиции не используется.
*** порядок вставки ключей гарантирован с Python 3.7.
Кратко по назначению:
list— упорядоченный изменяемый набор с позициями0, 1, 2…; дубликаты разрешены; удобен для очередей задач, логов, результатов запросов.tuple— как список по доступуt[i], но после создания не меняется; подходит для координат, записей "полей", ключейdict, возврата нескольких значений из функции.set— только уникальные элементы; позиционного индекса нет; быстрые проверкиx in sи операции|,&,-.dict— пары "ключ → значение"; ключи хешируемые и уникальные; значения могут повторяться.
lst = [10, 20, 10] # индекс, порядок, изменения, дубликаты
tpl = (10, 20, 10) # индекс и порядок; tpl[0] = 1 → TypeError
uniq = {10, 20, 10} # {10, 20}
phonebook = {"Аня": "+7…", "Борис": "+7…"} # phonebook["Аня"], не phonebook[0]
Выбор конкретной коллекции определяется требованиями к производительности, безопасности данных и логике алгоритма. Теория структур без привязки к Python — в разделе "Структуры данных"; обзор алгоритмов и сложности — в Алгоритмы и структуры данных.
Сводка операций по типам
list (изменяемый упорядоченный список):
| Действие | Синтаксис |
|---|---|
| Добавить в конец | append(value) |
| Вставить по индексу | insert(index, value) |
| Прочитать | lst[index] |
| Заменить | lst[index] = value |
| Удалить по индексу | pop(index) или del lst[index] |
| Удалить по значению | remove(value) |
set (уникальные элементы):
| Действие | Синтаксис |
|---|---|
| Добавить | add(value) |
| Удалить | remove(value) или discard(value) |
| Проверить | value in s |
dict (словарь):
| Действие | Синтаксис |
|---|---|
| Добавить или заменить | d[key] = value |
| Прочитать | d[key] или d.get(key) |
| Удалить | del d[key] или pop(key) |
tuple — только чтение t[index]; изменение после создания недоступно.
collections.deque (очередь с быстрыми операциями с обоих концов):
| Действие | Метод |
|---|---|
| В конец | append(value) |
| В начало | appendleft(value) |
| Снять с конца | pop() |
| Снять с начала | popleft() |
Списки (list).
Список — это упорядоченная, изменяемая коллекция элементов произвольных типов. Элементы списка хранятся последовательно и доступны по целочисленным индексам, начиная с нуля. Списки реализованы как динамические массивы с автоматическим управлением памятью.
Создание:
lst = [1, 2, 3]
fruits = ["яблоко", "банан", "вишня"]
print(fruits[1]) # банан — индекс с нуля
fruits[1] = "смородина"
Из другой последовательности (например, кортежа) — через конструктор list():
fruits = list(("яблоко", "банан", "вишня"))
Перебор в цикле for:
for item in fruits:
print(item)
Перебор в цикле for представляет собой конструкцию управления потоком выполнения, которая последовательно извлекает каждый элемент из итерируемого объекта, такого как список, кортеж или строка, и выполняет заданный блок кода для каждого из этих элементов, при этом переменная цикла последовательно принимает значения всех элементов до тех пор, пока итерируемый объект не будет полностью исчерпан.
Шаблон:
<список> = [<элемент>, <элемент>, ..., <элемент>]
<список>— имя переменной типаlist.- Элементы могут быть любого типа и не обязаны быть однородными.
Добавление элемента в список:
<список>.append(<значение>)
- Добавляет
<значение>в конец списка. - Метод изменяет исходный список.
Добавление элемента в список представляет собой операцию, выполняемую с помощью метода append, которая помещает переданный объект в конец существующего списка, увеличивая его длину на единицу, при этом новый элемент занимает последнюю позицию и остаётся доступным по своему индексу, а сам список изменяется непосредственно на месте без создания новой копии.
Расширение списка итерируемым объектом:
<список>.extend(<итерируемый_объект>)
- Добавляет все элементы из
<итерируемый_объект>(например, другого списка) в конец текущего списка.
Расширение списка итерируемым объектом представляет собой операцию, выполняемую с помощью метода extend, которая принимает любой итерируемый объект, например другой список, кортеж или строку, и добавляет все его элементы по отдельности в конец исходного списка, в отличие от операции добавления, которая поместила бы итерируемый объект как единый элемент.
Вставка элемента по индексу:
<список>.insert(<индекс>, <значение>)
- Вставляет
<значение>в позицию<индекс>, сдвигая остальные элементы вправо.
Вставка элемента по индексу представляет собой операцию, выполняемую с помощью метода insert, которая принимает позицию вставки и сам элемент, после чего помещает новый элемент на указанную позицию, сдвигая все последующие элементы на одну позицию вправо, при этом если индекс выходит за границы допустимого диапазона, элемент будет добавлен либо в начало, либо в конец списка.
Удаление элемента по значению:
<список>.remove(<значение>)
- Удаляет первое вхождение
<значение>из списка. - Если значение отсутствует — вызывается исключение
ValueError.
Удаление элемента по значению представляет собой операцию, выполняемую с помощью метода remove, которая находит первое вхождение указанного значения в списке и удаляет этот элемент, сдвигая все последующие элементы на одну позицию влево, при этом если переданное значение не найдено, возникает ошибка, и метод не возвращает удалённый элемент, а только изменяет сам список.
Удаление и получение элемента по индексу:
<элемент> = <список>.pop([<индекс>])
- Удаляет и возвращает элемент по указанному
<индекс>. По умолчанию — последний элемент (-1).
Удаление и получение элемента по индексу представляет собой операцию, выполняемую с помощью оператора del или метода pop, причём pop удаляет элемент по указанному индексу и возвращает его значение для дальнейшего использования, в то время как del просто удаляет элемент без возврата, и оба варианта сдвигают все последующие элементы на одну позицию влево, изменяя длину списка.
items = ["яблоко", "банан", "вишня"]
items.remove("банан") # по значению
last = items.pop() # снимает "вишня" с конца
del items[0] # удалить по индексу
items.clear() # оставить пустой список []
# del items # удалить имя items из программы
Разбор:
remove("банан")удаляет первое совпадение по значению.pop()удаляет и возвращает элемент, поэтому результат сохранен вlast.del items[0]удаляет элемент по индексу.clear()очищает содержимое списка, но сам объект списка остается существовать.
Сортировка списка:
<список>.sort(key=<функция>, reverse=<булево_значение>)
- Сортирует список на месте.
key— функция для получения ключа сравнения.reverse=True— сортировка по убыванию.
Сортировка списка представляет собой операцию упорядочивания элементов по определённому правилу, выполняемую с помощью метода sort, который изменяет исходный список, располагая его элементы в порядке возрастания по умолчанию, или с помощью встроенной функции sorted, которая возвращает новый отсортированный список, оставляя исходный неизменным, при этом можно задать пользовательскую функцию сравнения или изменить порядок на убывающий через соответствующие параметры.
Разворот списка
Упорядоченный список можно пройти с конца к началу пятью распространёнными способами. Главное различие — меняется ли исходный объект или создаётся новая последовательность.
| Способ | Код | Исходный list | Что возвращается |
|---|---|---|---|
Метод reverse() | lst.reverse() | меняется | None |
| Срез | lst[::-1] | без изменений | новый list |
reversed() | list(reversed(lst)) | без изменений | новый list |
Цикл с insert(0, …) | см. ниже | без изменений | новый list |
Цикл с append по индексам | см. ниже | без изменений | новый list |
1. Метод reverse() — на месте
my_list = [1, 2, 3, 4, 5]
my_list.reverse()
print(my_list) # [5, 4, 3, 2, 1]
list.reverse() переворачивает элементы в том же объекте и возвращает None. Переменная my_list по-прежнему ссылается на изменённый список.
2. Срез [::-1] — новый список
my_list = [1, 2, 3, 4, 5]
reversed_list = my_list[::-1]
print(reversed_list) # [5, 4, 3, 2, 1]
print(my_list) # [1, 2, 3, 4, 5]
Синтаксис lst[start:stop:step] с step = -1 идёт от последнего индекса к нулевому. Исходный список остаётся прежним. Тот же приём для строк — в однострочных приёмах.
3. Встроенная reversed()
my_list = [1, 2, 3, 4, 5]
reversed_list = list(reversed(my_list))
reversed() возвращает итератор, а не список. Для материализации нужен list(...). Исходная коллекция не меняется. В цикле for x in reversed(lst) копию всего списка создавать не обязательно.
4. Цикл с insert(0, …)
my_list = [1, 2, 3, 4, 5]
r_list = []
for i in my_list:
r_list.insert(0, i)
print(r_list) # [5, 4, 3, 2, 1]
Каждый insert(0, i) сдвигает уже вставленные элементы, поэтому на длинных списках сложность растёт квадратично. Способ полезен на учебных задачах, в продакшене его редко выбирают.
5. Цикл с append по индексам с конца
my_list = [1, 2, 3, 4, 5]
r_list = []
for i in range(len(my_list) - 1, -1, -1):
r_list.append(my_list[i])
print(r_list) # [5, 4, 3, 2, 1]
Линейная работа по длине списка: индексы идут от len - 1 до 0 с шагом -1. Читается нагляднее, чем вариант с insert, но уступает срезу и reversed() по лаконичности.
Разворот на месте — lst.reverse(). Копия в обратном порядке при сохранении исходного порядка — lst[::-1] или list(reversed(lst)). Срез и reversed() — привычные идиомы; циклы помогают понять индексы и оценку сложности.
Индексация и срезы.
Индексация представляет собой механизм доступа к отдельным элементам последовательности с использованием квадратных скобок и указания целочисленного индекса, который позволяет не только читать значение элемента, но и изменять его, если последовательность является изменяемой, и является основным способом работы с позиционными данными в структурах данных.
Срезы представляют собой операцию извлечения подпоследовательности из исходной последовательности с помощью квадратных скобок и указания начального и конечного индексов через двоеточие, при этом можно также задать шаг, что позволяет выбрать каждый второй элемент или даже развернуть последовательность, причём срез всегда создаёт новый объект и не изменяет исходную последовательность.
Доступ к элементам осуществляется по индексу:
lst[0] # первый элемент
lst[-1] # последний элемент
Срезы позволяют извлекать подпоследовательности:
lst[1:3] # элементы с индексами 1 и 2
lst[::2] # каждый второй элемент
lst[::-1] # весь список в обратном порядке (новый list)
Срезы возвращают новый объект list. Они поддерживают шаг, отрицательные индексы и обратный порядок. Подробнее про все способы разворота — выше.
Списки имеют следующие методы:
append(x)- Добавляет элемент x в конец списка.extend(iterable)- Добавляет все элементы итерируемого объекта в конец.- Вставляет элемент x на позицию i.
insert(i, x)
remove(x)- Удаляет первое вхождение элемента x.pop([i])- Удаляет и возвращает элемент по индексу (по умолчанию — последний).clear()- Удаляет все элементы, список остаётся[].count(x)- Возвращает количество вхождений элемента x.sort(key=None, reverse=False)- Сортирует список in-place.reverse()- Переворачивает список in-place.copy()- Создаёт поверхностную копию списка.
numbers = [5, 2, 8, 1]
numbers.sort()
print(numbers) # [1, 2, 5, 8]
numbers.reverse()
print(numbers) # [8, 5, 2, 1]
Разбор:
sort()сортирует список на месте и меняет порядок элементов в текущем объекте.reverse()также работает на месте и инвертирует порядок (см. разворот списка).- чтобы сохранить исходный порядок, используйте
sorted(numbers)и срезnumbers[::-1]илиlist(reversed(numbers)).
Методы sort и reverse модифицируют исходный объект и возвращают None.
Списки гетерогенны (могут быть разных типов), изменяемы (допускается добавление, удаление, замена элементов), и представляют собой массив указателей на объекты. При расширении происходит перераспределение памяти с запасом.
Гетерогенность является свойством структур данных в Python, которое позволяет хранить в одной коллекции элементы различных типов данных одновременно, например числа, строки, логические значения и даже другие вложенные коллекции, что отражает динамическую природу языка и даёт большую гибкость при работе с разнородными данными.
Бинарные списки: array.array используются для эффективного хранения числовых данных большого объёма. Этот тип представляет собой массив примитивных значений (например, целых или вещественных чисел) фиксированного размера.
import array
arr = array.array('i', [1, 2, 3]) # массив 32-битных целых
Такие списки занимают меньше памяти по сравнению с обычным списком, быстрее при последовательном доступе и поддерживают те же операции, что и списки (индексация, срезы), но только для однотипных данных. Но - не поддерживают гетерогенные данные.
Если же требуется получить и использовать именно индекс, а не элемент, тогда используется функция enumerate():
my_list = ["яблоко", "банан", "апельсин", "груша"]
for index, item in enumerate(my_list):
print(f"Индекс: {index}, Элемент: {item}")
Кортежи (tuple)
Кортеж — это неизменяемый список. Всё.
# Список (можно менять)
my_list = [1, 2, 3]
my_list[0] = 999 # работает
# Кортеж (нельзя менять)
my_tuple = (1, 2, 3)
my_tuple[0] = 999 # Ошибка!
Это даёт нам:
- защиту от случайных изменений;
- возможность использовать как ключ;
- возможность возвращать несколько значений из функции;
- производительность (он занимает меньше памяти).
# Кортеж — всё, что не меняется
coordinates = (55.752, 37.615) # координаты Красной площади
rgb_color = (255, 0, 0) # красный цвет
menu_position = ('File', 'Open') # путь в меню
# Список — то, что меняется
users = ['alex', 'john', 'anna'] # будут добавляться/удаляться
cart = [1, 2, 3] # товары в корзине (пополняется)
Если тебе нужно менять коллекцию — бери список (list). Если не нужно менять и просто читать — бери кортеж (tuple). А если не уверен — бери список, это проще. Кортежи — это оптимизация и защита от дурака (от себя же).
Кортеж — это упорядоченная, неизменяемая коллекция элементов произвольных типов. После создания кортеж нельзя модифицировать: нельзя добавлять, удалять или заменять элементы. Кортежи неизменяемые (чтобы гарантировать целостность данных), хэшируемые (сам кортеж может использовать в качестве ключа в словаре или элементе множества), производительны и применяются часто для представления составных данных, например, координат (x, y) или возврат нескольких значений из функции.
Пример:
t = (1, 2, 3)
t = 1, 2, 3 # скобки опциональны
coords = ("помидор", "огурец", "лук")
print(coords[1]) # огурец
Из последовательности — конструктор tuple() (часто с двойными скобками внутри, чтобы не спутать с группировкой выражений):
coords = tuple(("помидор", "огурец", "лук"))
После создания элемент нельзя заменить — будет TypeError:
coords = ("помидор", "огурец", "лук")
# coords[1] = "морковка" # TypeError —'tuple' object does not support item assignment
Удалить можно только весь кортеж через del, отдельные элементы не снимаются.
Кортежи поддерживают ограниченный набор методов:
count(x)— количество вхождений элемента x.index(x[, start[, end]])— индекс первого вхождения x.
Поскольку кортежи неизменяемы, методы модификации отсутствуют.
Создание кортежа:
<кортеж> = (<элемент>, <элемент>, ..., <элемент>)
или
<кортеж> = <элемент>, <элемент>, ..., <элемент>
Получение количества вхождений значения в кортеж:
<число> = <кортеж>.count(<значение>)
- Возвращает количество элементов, равных
<значение>.
Получение индекса первого вхождения значения:
<индекс> = <кортеж>.index(<значение>[, <начало>[, <конец>]])
- Возвращает индекс первого совпадения
<значение>в пределах[начало:конец].
Множества (set)
Множество — это неупорядоченная, изменяемая коллекция уникальных элементов. Элементы множества должны быть хэшируемыми (т.е. иметь метод __hash__ и быть сравнимыми).
Создание:
s = {1, 2, 3}
s = set([1, 2, 3]) # из итерируемого
# Список с дубликатами
items = ["тигр", "лев", "панда", "тигр", "заяц", "лев"]
# Превращаем в множество — дубликаты исчезнут!
unique_items = set(items)
print(unique_items) # {'тигр', 'лев', 'панда', 'заяц'}
Разбор:
set(items)создает множество из итерируемого объекта.- множество хранит только уникальные значения, повторы удаляются автоматически.
- порядок элементов у
setне предназначен для бизнес-логики.
Пустое множество создаётся только через set(), так как {} интерпретируется как пустой словарь.
Множества автоматически устраняют дубликаты:
{1, 1, 2} # → {1, 2}
Множества бывают изменяемыми и неизменяемыми.
Методы изменяемых множеств (set):
add(x)— добавить элемент.remove(x)— удалить элемент; ошибка, если нет.discard(x)— удалить, если есть; ошибки не возникает.pop()— удалить и вернуть произвольный элемент.clear()— очистить множество.
frozenset — неизменяемая версия множества. Поддерживает все операции чтения и теоретико-множественные операции, но не позволяет модифицировать содержимое. Полезен как ключ в словаре или элемент другого множества.
# set - изменяемый
mutable_set = {1, 2, 3}
mutable_set.add(4) # Работает
mutable_set.remove(2) # Работает
# frozenset - неизменяемый
frozen = frozenset({1, 2, 3})
# frozen.add(4) # Ошибка — AttributeError
# frozen.remove(2) # Ошибка — AttributeError
# frozenset хэшируемый
hash(frozenset({1, 2, 3})) # Работает
# set не хэшируемый
# hash({1, 2, 3}) # Ошибка — TypeError
# frozenset можно использовать как ключ
d = {frozenset({1, 2}): "value"} # Работает
# set нельзя использовать как ключ
# d = {{1, 2} — "value"} # Ошибка: TypeError
Объединение: | или .union()
first = {"тигр", "панда", "заяц"}
second = {"лев", "заяц", "медведь"}
all_animals = first | second
print(all_animals) # Все звери без повторов
Создание множества:
<множество> = {<элемент>, <элемент>, ..., <элемент>}
или
<множество> = set(<итерируемый_объект>)
- Все элементы должны быть хэшируемыми.
- Автоматически удаляются дубликаты.
Добавление элемента в множество:
<множество>.add(<значение>)
- Добавляет
<значение>в множество, если оно ещё не присутствует.
Удаление элемента из множества (с ошибкой при отсутствии):
<множество>.remove(<значение>)
- Удаляет
<значение>. Если его нет — возникает исключениеKeyError.
Удаление элемента из множества (без ошибки):
<множество>.discard(<значение>)
- Удаляет
<значение>, если оно есть. Не вызывает исключение при отсутствии.
Объединение двух множеств:
<новое_множество> = <множество_1> | <множество_2>
или
<новое_множество> = <множество_1>.union(<множество_2>)
- Возвращает новое множество, содержащее все уникальные элементы из обоих исходных.
Преобразование:
# Преобразование set в frozenset
frozen = frozenset({1, 2, 3})
# Преобразование frozenset в set
mutable = set(frozenset({1, 2, 3}))
Play ITЗагрузка интерактивного демо…
Словари (dict)
Словарь — это изменяемая коллекция пар "ключ-значение", где ключи уникальны и хэшируемы, а значения могут быть любыми объектами. Доступ к значениям осуществляется по ключу. Словари реализованы как хеш-таблицы с открытой адресацией.
Создание:
d = {'a': 1, 'b': 2}
d = dict(a=1, b=2)
Ключи должны быть хэшируемыми (числа, строки, кортежи из хэшируемых объектов и т.д.). Значения же произвольные объекты, включая изменяемые. Словари сохраняют порядок вставки с Python 3.7+ (в 3.6 — как особенность CPython, с 3.7 — как гарантия языка).
Методы словаря
Девять методов, которые чаще всего нужны в повседневном коде (плюс copy() для копии):
| Метод | Назначение |
|---|---|
get(key[, default]) | Значение по ключу; если ключа нет — default (по умолчанию None), без KeyError |
keys() | Представление ключей (итерируемое) |
values() | Представление значений |
items() | Пары (ключ, значение) |
update(other) | Добавить или перезаписать пары из другого словаря или итерируемого |
setdefault(key, default) | Вернуть значение; если ключа нет — записать default и вернуть его |
pop(key[, default]) | Удалить ключ и вернуть значение; при отсутствии ключа — default или KeyError |
popitem() | Удалить и вернуть последнюю вставленную пару (ключ, значение) |
clear() | Удалить все пары |
copy() | Поверхностная копия |
keys(), values() и items() возвращают представления (views), а не списки. Для вывода в консоль удобно обернуть в list(...).
Один словарь — по шагам, как на шпаргалке:
Код ITЗагрузка примера кода…
Запись d[key] при отсутствии ключа вызывает KeyError (см. исключения). Метод get() подходит, когда отсутствие ключа — нормальный сценарий — конфиг, кэш, счётчики (freq.get(token, 0) + 1 ниже в практических примерах).
Пример — классический словарь-переводчик:
translator = {
"cat": "кошка",
"dog": "собака",
"house": "дом",
"sun": "солнце",
"book": "книга"
}
word = input("Введите слово на английском: ")
translation = translator.get(word, "Не знаю такого слова")
print(f"Перевод: {translation}")
Разбор:
- словарь
translatorхранит парыанглийское_слово -> перевод. input(...)получает ключ для поиска в словаре.get(word, "Не знаю такого слова")возвращает перевод или значение по умолчанию, если ключ отсутствует.- финальная
f-строка печатает уже готовый результат поиска.
Создание словаря:
<словарь> = {<ключ>: <значение>, <ключ>: <значение>, ..., <ключ>: <значение>}
или
<словарь> = dict(<ключ>=<значение>, ...)
- Ключи должны быть хэшируемыми; значения — произвольными.
Получение значения по ключу (с безопасным доступом):
<значение> = <словарь>.get(<ключ>[, <значение_по_умолчанию>])
- Возвращает значение, связанное с
<ключ>, или<значение_по_умолчанию>, если ключ отсутствует.
Установка значения по умолчанию при отсутствии ключа:
<значение> = <словарь>.setdefault(<ключ>, <значение_по_умолчанию>)
- Если
<ключ>отсутствует, добавляет пару<ключ>: <значение_по_умолчанию>и возвращает это значение. - Если ключ есть — возвращает существующее значение.
Обновление словаря парами из другого словаря:
<словарь>.update(<другой_словарь>)
- Добавляет или заменяет пары "ключ-значение" из
<другой_словарь>в текущий словарь.
Удаление по ключу и снятие последней пары:
<значение> = <словарь>.pop(<ключ>[, <значение_по_умолчанию>])
<пара> = <словарь>.popitem()
<словарь>.clear()
popвозвращает значение удалённого ключа;popitem— кортеж(ключ, значение)последней вставки;clearочищает весь словарь.
Итерация по ключам, значениям и парам:
for <ключ> in <словарь>.keys():
...
for <значение> in <словарь>.values():
...
for <ключ>, <значение> in <словарь>.items():
...
.keys(),.values(),.items()возвращают представления (views), а не списки.
Практические сценарии
Подсчёт частот
Подсчёт частот представляет собой процесс определения количества вхождений каждого уникального элемента в списке, который часто выполняется с использованием стандартного класса Counter из модуля collections, который принимает итерируемый объект и возвращает словарь, где ключами являются уникальные элементы, а значениями их частоты встречаемости.
text = ["api", "db", "api", "cache", "api", "db"]
freq = {}
for token in text:
freq[token] = freq.get(token, 0) + 1
print(freq) # {'api': 3, 'db': 2, 'cache': 1}
Разбор:
- цикл
for token in textпроходит по каждому элементу списка. freq.get(token, 0)берет текущее значение счетчика или0, если ключ встречается впервые.- выражение
+ 1увеличивает счетчик, после чего обновленное значение записывается вfreq[token].
Удаление дублей с сохранением порядка
Удаление дублей с сохранением порядка представляет собой задачу получения нового списка, в котором каждый элемент встречается только один раз, при этом сохраняется относительный порядок первого появления каждого элемента, и которая чаще всего решается путём прохода по исходному списку и добавления элементов во вспомогательную структуру данных, например множество, для проверки уникальности.
items = ["a", "b", "a", "c", "b"]
unique = list(dict.fromkeys(items))
print(unique) # ['a', 'b', 'c']
Очередь задач
Очередь задач представляет собой абстрактную структуру данных, работающую по принципу первого пришёл первым ушёл, которая используется для хранения заданий или элементов, ожидающих обработки, при этом добавление новых задач происходит в конец очереди, а извлечение и обработка выполняются из её начала, что позволяет организовать упорядоченное и справедливое выполнение операций в различных алгоритмах и системах.
from collections import deque
queue = deque(["task-1", "task-2"])
queue.append("task-3")
current = queue.popleft()
print(current) # task-1
Типичные ошибки при работе с коллекциями
- Использование изменяемого объекта как ключа словаря.
- Ожидание стабильного порядка у
setв бизнес-логике. - Неявное копирование вложенных структур вместо
copy.deepcopy. - Выбор
listдля операции "проверить наличие" в больших наборах, где нуженset.
Для корректной копии вложенных структур:
import copy
config = {"limits": [1, 2, 3]}
clone = copy.deepcopy(config)
Связанные материалы
- Базовые алгоритмы и Big O: Алгоритмы и структуры данных
- Логика обхода в циклах: Управляющие конструкции
- Ленивые обходы и пайплайны: Итераторы и генераторы
- Сложность операций с коллекциями: Нотация Большое O · Lab / Big-O — 1128
- Задачи ЕГЭ/олимпиад (
list,dict,set,Counter): Lab / 1122
Как выбирать коллекцию без лишних сомнений
Полезная инженерная эвристика:
- Нужен порядок и изменения — берите
list. - Нужен порядок без изменений — берите
tuple. - Нужен быстрый доступ по ключу — берите
dict. - Нужна уникальность и операции пересечения/объединения — берите
set.
Если структура выбрана верно, код становится быстрее и проще, чем при попытке "решить всё списком".
В задачах ЕГЭ и олимпиад те же типы постоянно встречаются в коде — list для массива чисел, set для "уже видели", dict/Counter для частот — готовые примеры с разбором — Lab / 1122. Почему x in list в цикле даёт O(n²), а x in set — O(n) — Lab / 1128, ловушки Python.