Структуры данных: списки, словари и множества
Три рабочих лошадки программиста — и как выбрать правильную, чтобы программа была и понятной, и быстрой.
Структура данных — способ организации данных в памяти, определяющий, какие операции над ними удобны и быстры.
Зачем это нужно
Выбор структуры данных — половина успеха программы. Хранить список покупок и хранить телефонную книгу — задачи разные, и для них нужны разные «контейнеры». Неправильный выбор делает код либо громоздким, либо медленным. В этом уроке мы разберём три главные структуры Python — список, словарь и множество — не как набор синтаксиса, а как инструменты с характером: у каждого свои сильные и слабые стороны.
Есть знаменитая мысль, которую любят повторять опытные разработчики: «выберите правильные структуры данных, и алгоритмы напишутся почти сами собой». Звучит как преувеличение, но это правда. Очень часто задача, мучительная при одном представлении данных, становится тривиальной при другом. Нужно быстро проверять, встречалось ли слово? Со списком вы будете перебирать его снова и снова, а с множеством ответ приходит мгновенно. Нужно по имени найти телефон? Со списком пар придётся искать перебором, а словарь даёт ответ за один шаг. Поэтому грамотный программист, прежде чем писать цикл, задаёт себе вопрос: «а в каком виде эти данные хранить, чтобы нужные операции были дешёвыми?» Этот урок учит именно такому мышлению — смотреть на данные через призму операций, которые с ними предстоит делать.
Список: упорядоченная последовательность
Список (list) хранит элементы по порядку, с доступом по индексу. Это аналог нумерованного ряда ячеек. Списки изменяемы: можно добавлять, удалять, менять элементы. Доступ по индексу мгновенный, а вот поиск элемента по значению требует просмотра — в худшем случае всего списка.
marks = [5, 4, 5, 3, 5, 4]
marks.append(2) # добавить в конец
print("оценки:", marks)
print("первая:", marks[0], " последняя:", marks[-1])
print("срез 1..3:", marks[1:4])
print("средний балл:", round(sum(marks) / len(marks), 2))
print("сколько пятёрок:", marks.count(5))
Вывод:
оценки: [5, 4, 5, 3, 5, 4, 2] первая: 5 последняя: 2 срез 1..3: [4, 5, 3] средний балл: 4.0 сколько пятёрок: 3
Генераторы списков: коротко и быстро
Вместо цикла с append Python предлагает компактную запись — генератор списка (list comprehension). Это не просто «красиво»: такой код часто читается как математическая формула «множество всех x, таких что…».
# квадраты чётных чисел от 1 до 10
squares = [x * x for x in range(1, 11) if x % 2 == 0]
print(squares)
# длины слов
words = ["информатика", "Python", "код"]
lengths = [len(w) for w in words]
print(lengths)
Вывод:
[4, 16, 36, 64, 100] [11, 6, 3]
Словарь: пары «ключ → значение»
Словарь (dict) хранит соответствия: по ключу мгновенно получаем значение. Это телефонная книга, оценочный журнал, частотный словарь. Главное достоинство — поиск по ключу за константное время (в среднем), потому что внутри работает хеш-таблица. Сравните: чтобы найти в списке из миллиона записей нужную, придётся перебирать; в словаре доступ почти мгновенный независимо от размера.
capitals = {"Россия": "Москва", "Япония": "Токио", "Перу": "Лима"}
print("Столица Японии:", capitals["Япония"])
capitals["Канада"] = "Оттава" # добавили запись
print("есть Перу?", "Перу" in capitals)
print("безопасно:", capitals.get("Бразилия", "неизвестно"))
for country, city in capitals.items():
print(f" {country} → {city}")
Вывод:
Столица Японии: Токио есть Перу? True безопасно: неизвестно Россия → Москва Япония → Токио Перу → Лима Канада → Оттава
Частотный словарь — классический приём
Словарь идеален для подсчёта: сколько раз встречается каждый элемент. Это ядро многих задач ЕГЭ и анализа текста. Посчитаем частоту букв в слове:
word = "информатика"
freq = {}
for ch in word:
freq[ch] = freq.get(ch, 0) + 1 # +1 к счётчику буквы
for ch, n in sorted(freq.items()):
print(f"'{ch}': {n}")
top = max(freq, key=freq.get) # самая частая буква
print("Чаще всего:", top, "—", freq[top], "раза")
Вывод:
'а': 2 'и': 2 'к': 1 'м': 1 'н': 1 'о': 1 'р': 1 'т': 1 'ф': 1 Чаще всего: и — 2 раза
Множество: уникальность и операции теории множеств
Множество (set) хранит только уникальные элементы без порядка. Оно создано для двух задач: убрать дубликаты и быстро проверить принадлежность. А ещё оно умеет настоящие операции теории множеств — объединение, пересечение, разность:
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7}
print("объединение:", a | b) # всё вместе
print("пересечение:", a & b) # общее
print("разность a-b:", a - b) # только в a
# убрать дубликаты из списка
nums = [3, 1, 2, 3, 3, 1, 5]
print("уникальные:", sorted(set(nums)))
print("5 в множестве a?", 5 in a)
Вывод:
объединение: {1, 2, 3, 4, 5, 6, 7}
пересечение: {4, 5}
разность a-b: {1, 2, 3}
уникальные: [1, 2, 3, 5]
5 в множестве a? True
Когда что выбирать
| Нужно… | Структура | Почему |
| хранить по порядку, обращаться по индексу | список | сохраняет порядок, доступ по индексу мгновенный |
| искать значение по ключу | словарь | поиск по ключу почти мгновенный |
| хранить уникальные, быстро проверять «есть ли» | множество | нет дубликатов, проверка вхождения быстрая |
Маленькая хитрость про скорость: проверка x in список просматривает элементы по очереди (медленно для больших данных), а x in множество или x in словарь — почти мгновенна. Если вы часто проверяете принадлежность, переведите список в множество.
Попробуй сам
Соберём мини-анализатор текста: уникальные слова, частоты и самое длинное слово. Меняйте текст и наблюдайте результат.
text = "кот ловит мышь кот спит мышь убегает кот"
words = text.split()
unique = set(words)
freq = {}
for w in words:
freq[w] = freq.get(w, 0) + 1
longest = max(words, key=len)
print("Всего слов:", len(words))
print("Уникальных:", len(unique))
print("Частоты:", dict(sorted(freq.items())))
print("Самое длинное:", longest)
Вывод:
Всего слов: 8
Уникальных: 5
Частоты: {'кот': 3, 'ловит': 1, 'мышь': 2, 'спит': 1, 'убегает': 1}
Самое длинное: убегает
Частые ошибки
- Обращаются к несуществующему ключу.
d[key]даёт ошибку, если ключа нет; используйтеd.get(key, по_умолчанию). - Ждут порядок от множества. Множество не хранит порядок; чтобы вывести по порядку, оберните в
sorted. - Ищут
x in списокв цикле по большим данным. Это медленно; переведите список в множество. - Путают копию и ссылку.
b = aдля списка не создаёт копию — оба имени указывают на один список; нужнаa.copy().
Итоги
- Список — упорядочен, доступ по индексу мгновенный, поиск по значению — просмотром.
- Словарь — пары ключ→значение, поиск по ключу почти мгновенный (хеш-таблица).
- Множество — уникальные элементы, быстрая проверка вхождения и операции объединения/пересечения/разности.
- Генераторы списков — компактная и быстрая замена циклу с
append.
Закрепите практикой
Задачи с автоматической проверкой — решайте прямо здесь, не уходя из учебника.