3.2. Множества, словари

В этом параграфе мы продолжим изучать коллекции — но теперь познакомимся с неупорядоченными типами данных. Вы узнаете, как работают множества (set) и словари (dict), чем они отличаются от списков и в каких задачах используются. Научитесь проверять, содержится ли элемент в множестве, находить пересечения и разности, а также хранить и быстро получать значения по ключам. Мы разберёмся, как создавать множества и словари, выполнять над ними операции, использовать их методы и применять в реальных примера.

Ключевые вопросы параграфа

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

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

Множество — это тип коллекции, в которой автоматически удаляются повторяющиеся значения, а порядок не сохраняется. У множеств нет индексов, но с ними можно выполнять полезные операции: быстро проверять наличие элемента, находить пересечения и объединения, удалять дубли. Начнём с того, как создавать множества и преобразовывать в них другие коллекции.

Создание множества и преобразование из других коллекций

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

1vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}

Если нужно создать пустое множество, используют функцию set() без аргументов. А чтобы определить, сколько в нём элементов, подойдёт уже знакомая функция len():

1empty_set = set()
2print(f"Длина пустого множества равна {len(empty_set)}.")

Вывод программы:

Длина пустого множества равна 0.

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

1word = "коллекция"
2letters = set(word)
3print(letters)

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

{'е', 'о', 'и', 'я', 'к', 'л', 'ц'}
{'л', 'к', 'и', 'ц', 'я', 'е', 'о'}

Неупорядоченность и уникальность

У множеств есть две важные особенности:

  • Элементы не имеют фиксированного порядка. При каждом запуске программы порядок элементов может быть разным.
  • Элементы не повторяются. В множестве автоматически хранятся только уникальные значения — дубликаты удаляются.

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

Проверка принадлежности

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

1vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
2letter = input("Введите букву русского алфавита: ")
3if letter.lower() in vowels:
4    print("Гласная буква")
5else:
6    print("Согласная буква")

Перебор элементов множества

Пройти по множеству можно в цикле for:

1vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
2for letter in vowels:
3    print(letter)

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

Операции над множествами

Множества в Python позволяют выполнять основные множестенные операции, которые часто встречаются в задачах обработки данных.

Рассмотрим каждую из них.

  • Объединяет два множества — результат содержит все элементы из обоих. Повторы исключаются. Оператор: | или метод union().
    Python

Пример:

1s_1 = {1, 2, 3}
2s_2 = {3, 4, 5}
3s_union = s_1 | s_2
4# s_union = s_1.union(s_2)
5print(s_union)

Вывод программы:

{1, 2, 3, 4, 5}
  • Возвращает только те элементы, которые есть в обоих множествах. Оператор: & или метод intersection().

Python

Пример:

1s_1 = {1, 2, 3}
2s_2 = {3, 4, 5}
3s_intersection = s_1 & s_2
4# s_intersection = s_1.intersection(s_2)
5print(s_intersection)

Вывод программы:

{3}
  • Возвращает элементы из первого множества, которых нет во втором. Оператор: - или метод difference().

Python

Пример:

1s_1 = {1, 2, 3}
2s_2 = {3, 4, 5}
3s_dif = s_1 - s_2
4# s_dif = s_1.difference(s_2)
5print(s_dif)

Вывод программы:

{1, 2}
  • Возвращает элементы, которые есть только в одном из двух множеств (в первом или втором, но не в обоих). Оператор: ^ или метод symmetric_difference().

Python

Пример:

1s_1 = {1, 2, 3}
2s_2 = {3, 4, 5}
3s_sym_dif = s_1 ^ s_2
4# s_sym_dif = s_1.symmetric_difference(s_2)
5print(s_sym_dif)

Вывод программы:

{1, 2, 4, 5}

Пример: найти гласные в слове

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

1vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
2letters = set("коллекция")
3print(", ".join(letters & vowels))

Вывод программы:

о, я, и, е

Сравнение множеств

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

  • Проверяет, содержат ли два множества одни и те же элементы, независимо от порядка. Оператор: ==.
1s_1 = {1, 2, 3}
2s_2 = {3, 1, 2}
3print(s_1 == s_2)

Вывод программы:

True
  • ППроверяет, входят ли все элементы одного множества в другое. Оператор: <=.
1s_1 = {1, 2, 3}
2s_2 = {1, 2, 3, 4}
3print(s_1 <= s_2)

Вывод программы:

True

Проверяет, содержит ли множество все элементы другого множества. Оператор: >=.

1s_1 = {1, 2, 3, 4}
2s_2 = {1, 2, 3}
3print(s1 >= s2)

Вывод программы:

True

Методы, изменяющие множество

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

set.add(e)

Описание
Добавить элемент во множество

Пример:

1s = set()
2s.add(1)
3print(s)

Вывод:

{1}
set.remove(e)

Описание
Удалить элемент множества. Возвращает исключение KeyError, если элемент не принадлежит множеству

Пример:

1s = {1, 2, 3}
2s.remove(2)
3print(s)

Результат:

{1, 3}
set.discard(e)

Описание
Удалить элемент, если он принадлежит множеству

Пример:

1s = {1, 2, 3}
2s.discard(2)
3print(s)

Вывод:

{1, 3}
set.pop()

Описание
Вернуть и удалить произвольный элемент множества

Пример:

1s = {1, 2, 3}
2x = s.pop()
3print(x)
4print(s)

Вывод:

2
{1, 3}
set.clear()

Описание
Очистить множество, удалив все его элементы

Пример:

1s = {1, 2, 3}
2s.clear()
3print(s)

Вывод:

set()

Словари (dict)

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

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

Когда списков недостаточно

Допустим, нам нужно сохранить информацию о странах и их столицах. Один из способов — использовать список кортежей, где каждая пара содержит страну и её столицу:

1countries_and_capitals = [("Россия", "Москва"), ("США", "Вашингтон"), ("Франция", "Париж")]

Если мы хотим узнать столицу Франции, придётся пройтись по списку и найти нужную строку:

1countries_and_capitals = [("Россия", "Москва"), ("США", "Вашингтон"), ("Франция", "Париж")]
2for country in countries_and_capitals:
3    if country[0] == "Франция":
4      print(country[1])
5      break

Этот подход работает, но он не самый удобный — особенно при большом объёме данных.

Как устроен словарь

Словарь (dict) — это коллекция пар ключ : значение. Ключ может быть, например, названием страны, а значение — её столицей. Такое хранение позволяет обращаться к

1countries_and_capitals = {"Россия": "Москва",
2"США": "Вашингтон",
3"Франция": "Париж"}
4print(countries_and_capitals["Франция"])

Ключи и значения разделяются двоеточием, пары записываются в фигурных скобках и разделяются запятыми.Ключами могут быть неизменяемые типы данных: строки, числа, кортежи.Значения могут быть любого типа.

Добавление и изменение значений

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

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

1countries_and_capitals = {"Россия": "Москва",
2                          "США": "Вашингтон",
3                          "Франция": "Париж"}
4countries_and_capitals["Сербия"] = "Белград"
5print(countries_and_capitals)

Обратите внимание: при записи значения по уже существующему ключу, старое значение стирается, и ключ создаётся заново с новым значением.

1d = {"key": "old_value"}
2d["key"] = "new_value"
3print(d["key"])

Вывод программы:

new_value

Обработка ошибок и проверка ключа

Если попытаться получить значение по несуществующему ключу, программа завершится с ошибкой KeyError:

1countries_and_capitals = {"Россия": "Москва",
2                          "США": "Вашингтон",
3                          "Франция": "Париж"}
4print(countries_and_capitals["Сербия"])

Вывод программы:

KeyError: 'Сербия'

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

1countries_and_capitals = {"Россия": "Москва",
2                          "США": "Вашингтон",
3                          "Франция": "Париж"}
4if "Сербия" in countries_and_capitals:
5    print(countries_and_capitals["Сербия"])
6else:
7    print("Страна пока не добавлена в словарь")

Перебор словаря в цикле

Пройтись по всем ключам словаря можно с помощью цикла for. При этом на каждой итерации переменная цикла принимает ключ, а значение можно получить по этому ключу:

1countries_and_capitals = {"Россия": "Москва",
2"США": "Вашингтон",
3"Франция": "Париж"}
4for country in countries_and_capitals:
5    print(f"У страны {country} столица — {countries_and_capitals[country]}.")

Вывод программы:

У страны Россия столица — Москва.
У страны США столица — Вашингтон.
У страны Франция столица — Париж.

Значения-коллекции: пример с индексами строк

Значением в словаре может быть не только число или строка, но и коллекция — например, список. Это позволяет хранить по ключу сразу несколько связанных значений.

Рассмотрим пример: пользователь вводит названия стран построчно. Некоторые страны могут повторяться. Нужно сохранить, в каких строках (начиная с нулевой) встречалась каждая страна. Для этого создадим словарь, где ключ — это название страны, а значение — список номеров строк:

1# создаём пустой словарь
2countries = dict()
3# вводим первую строку до цикла (можно заменить, использовав оператор-морж)
4country = input()
5# создаём счётчик номеров строк
6str_number = 0
7# продолжаем цикл, пока не введена строка «СТОП»
8while country != "СТОП":
9    # если введённой страны нет в словаре, создаём ключ и записываем по ключу список из одного номера строки
10    if country not in countries:
11        countries[country] = [str_number]
12    # иначе добавляем в список по ключу новое значение номера строки
13    else:
14        countries[country].append(str_number)
15    # увеличиваем счётчик
16    str_number += 1
17    # вводим следующую строку
18    country = input()
19# выводим название страны и полученные списки с новой строки
20for country in countries:
21    print(f"{country}: {countries[country]}")

Пример ввода:

США
США
Россия
Россия
Россия
Франция
Сербия
СТОП

Вывод программы:

США: [0, 1]
Россия: [2, 3, 4]
Франция: [5]
Сербия: [6]

Методы словаря

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

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

len(d)

Описание
Возвращает количество ключей в словаре

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2print(len(d))

Вывод:

3
del d[key]

Описание
Удалить ключ из словаря. Если ключа нет, то вызывается исключение KeyError

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2del d["b"]
3print(d)

Вывод:


dict.clear()

Описание
Удалить все ключи и значения в словаре

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2d.clear()
3print(d)

Вывод:

d = {"a": 1, "b": 2, "c": 3}
d_new = d.copy()
print(d_new)
dict.get(key, default)

Описание
Возвращает значение по ключу key. Если ключа нет, то возвращает значение default

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2print(d.get("e", "Ключа нет в словаре"))

Вывод:

Ключа нет в словаре
dict.items()

Описание
Возвращает итерируемый объект, состоящий из кортежей (ключ, значение) словаря

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2for key, value in d.items():
3    print(key, value)

Вывод:

a 1
b 2
c 3
dict.keys()

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

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2for key in d.keys():
3    print(key)

Вывод:

a
b
c
d.pop(key, default)

Описание
Возвращает значение по ключу key и удаляет его из словаря. Если ключа нет, то возвращает default

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2x = d.pop("a")
3print(x)

Вывод:

1
dict.values()

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

Пример:

1d = {"a": 1, "b": 2, "c": 3}
2for value in d.values():
3    print(value)

Вывод:

1
2
3

Тот же пример с использованием get()

Ранее мы реализовали программу, которая сохраняет номера строк, в которых встречалась каждая страна. Теперь перепишем её с использованием метода get(). Это позволит сократить код без потери логики.

1# создаём пустой словарь
2countries = dict()
3# вводим первую строку до цикла (можно заменить, использовав оператор-морж)
4country = input()
5# создаём счётчик номеров строк
6str_number = 0
7# продолжаем цикл, пока не введена строка «СТОП»
8while country != "СТОП":
9    # Если страна country есть среди ключей, то get() возвращает список, 
10    # хранящийся по этому ключу, иначе get() возвращает пустой список. 
11    # Добавляем в список значение str_number.
12    countries[country] = countries.get(country, []) + [str_number]
13    # увеличиваем счётчик
14    str_number += 1
15    # вводим следующую строку
16    country = input()
17# выводим название страны и полученные списки с новой строки
18for country in countries:
19    print(f"{country}: {countries[country]}")

Метод get() позволил заменить четыре строчки кода одной. Попробуйте запустить оба варианта программы — вывод будет одинаковым.

✅ У вас получилось разобраться с множествами и словарями?

Если вы прошли все примеры, попробовали поработать с ключами, значениями, операциями и методами — вы отлично продвинулись!

👉 Оценить этот параграф

Что дальше

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

Дальше мы сделаем ещё один шаг вперёд: разберёмся, как быстро создавать и фильтровать списки с помощью списочных выражений, узнаем, что такое генераторы и итераторы, а заодно заглянем «под капот» — и поймём, как Python хранит переменные в памяти.

В следующем параграфе:

  • вы познакомитесь со списочными выражениями (и узнаете, почему они читаются проще, чем for + append);
  • научитесь использовать вложенные циклы и условия прямо внутри списков;
  • узнаете, как устроены генераторы и почему они экономят память;
  • и, наконец, разберётесь, почему у переменных может меняться идентификатор, и что это вообще значит.

А пока вы не ушли дальше — закрепите материал на практике:

  • Отметьте, что урок прочитан при помощи кнопки ниже.
  • Пройдите мини-квиз, чтобы проверить, насколько хорошо вы усвоили тему.
  • Перейдите к задачам этого параграфа и потренируйтесь.
  • Перед этим — загляните в короткий гайд о том, как работает система проверки.

Хотите обсудить, задать вопрос или не понимаете, почему код не работает? Мы всё предусмотрели — вступайте в сообщество Хендбука! Там студенты помогают друг другу разобраться..

Ключевые выводы параграфа

  • Множество (set) — неупорядоченная коллекция без повторов; используется для хранения уникальных значений и проверки принадлежности.
  • Множества поддерживают операции: объединение, пересечение, разность и симметричная разность.
  • Словарь (dict) хранит значения по ключам; ключи должны быть неизменяемыми типами, значения — любыми.
  • Для безопасного получения значений из словаря используют метод get() и проверку ключей через in.
  • В словарях можно хранить вложенные коллекции и перебирать данные по ключам, значениям или парам.

Отмечайте параграфы как прочитанные чтобы видеть свой прогресс обучения

Вступайте в сообщество хендбука

Здесь можно найти единомышленников, экспертов и просто интересных собеседников. А ещё — получить помощь или поделиться знаниями.
Вступить
Сообщить об ошибке
Предыдущий параграф3.1. Строки, кортежи, списки

В этом параграфе мы начнём знакомство с коллекциями — специальными типами данных, которые позволяют хранить и обрабатывать несколько значений одновременно. Мы разберёмся, как обращаться к элементам коллекций, как проходить по ним в цикле, использовать срезы и встроенные методы. А ещё научимся отличать изменяемые коллекции от неизменяемых — это важно для понимания, как работает память в Python.Рассмотрим упорядоченные коллекции, индексацию, методы и функции для их обработки.

Следующий параграф3.3. Списочные выражения. Модель памяти для типов языка Python

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