3.2. Множества, словари
В этой статье мы продолжим изучать коллекции — но теперь познакомимся с неупорядоченными типами данных. Вы узнаете, как работают множества (set) и словари (dict), чем они отличаются от списков и в каких задачах используются. Научитесь проверять, содержится ли элемент в множестве, находить пересечения и разности, а также хранить и быстро получать значения по ключам. Мы разберёмся, как создавать множества и словари, выполнять над ними операции, использовать их методы и применять в реальных примерах.
Ключевые вопросы статьи
- Чем множества отличаются от списков и зачем нужны?
- Как устроено множество и какие операции с ним поддерживаются?
- Что такое словарь и как обращаться к элементам по ключу?
- Как добавлять и удалять элементы в словарях?
- Какие методы доступны у множеств и словарей?
Множества (set)
Множество — это тип коллекции, в которой автоматически удаляются повторяющиеся значения, а порядок не сохраняется. У множеств нет индексов, но с ними можно выполнять полезные операции: быстро проверять наличие элемента, находить пересечения и объединения, удалять дубли. Начнём с того, как создавать множества и преобразовывать в них другие коллекции.
Создание множества и преобразование из других коллекций
Чтобы создать множество, перечислите элементы в фигурных скобках:
vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
Если нужно создать пустое множество, используют функцию set() без аргументов. А чтобы определить, сколько в нём элементов, подойдёт уже знакомая функция len():
empty_set = set()
print(f"Длина пустого множества равна {len(empty_set)}.")
Вывод программы:
Длина пустого множества равна 0.
Множество можно также получить из другой коллекции. Например, вот как преобразовать строку в множество — получится набор уникальных символов:
word = "коллекция"
letters = set(word)
print(letters)
При каждом запуске порядок элементов может отличаться:
{'е', 'о', 'и', 'я', 'к', 'л', 'ц'}
{'л', 'к', 'и', 'ц', 'я', 'е', 'о'}
Неупорядоченность и уникальность
У множеств есть две важные особенности:
- Элементы не имеют фиксированного порядка. При каждом запуске программы порядок элементов может быть разным.
- Элементы не повторяются. В множестве автоматически хранятся только уникальные значения — дубликаты удаляются.
Поэтому в примере с преобразованием строки в множество мы получили набор уникальных символов, но потеряли их порядок.
Проверка принадлежности
Чтобы проверить, есть ли значение во множестве, используют оператор in. Например, определим, является ли введённая буква гласной:
vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
letter = input("Введите букву русского алфавита: ")
if letter.lower() in vowels:
print("Гласная буква")
else:
print("Согласная буква")
Перебор элементов множества
Пройти по множеству можно в цикле for:
vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
for letter in vowels:
print(letter)
Поскольку порядок элементов не фиксирован, при каждом запуске результат может отличаться — и это нормально для множеств.
Операции над множествами
Множества в Python позволяют выполнять основные множественные операции, которые часто встречаются в задачах обработки данных.
Рассмотрим каждую из них.
- Объединяет два множества — результат содержит все элементы из обоих. Повторы исключаются. Оператор: | или метод union().
Пример:
s_1 = {1, 2, 3}
s_2 = {3, 4, 5}
s_union = s_1 | s_2
# s_union = s_1.union(s_2)
print(s_union)
Вывод программы:
{1, 2, 3, 4, 5}
- Возвращает только те элементы, которые есть в обоих множествах. Оператор:
&или методintersection().
Пример:
s_1 = {1, 2, 3}
s_2 = {3, 4, 5}
s_intersection = s_1 & s_2
# s_intersection = s_1.intersection(s_2)
print(s_intersection)
Вывод программы:
{3}
- Возвращает элементы из первого множества, которых нет во втором. Оператор:
-или методdifference().
Пример:
s_1 = {1, 2, 3}
s_2 = {3, 4, 5}
s_dif = s_1 - s_2
# s_dif = s_1.difference(s_2)
print(s_dif)
Вывод программы:
{1, 2}
- Возвращает элементы, которые есть только в одном из двух множеств (в первом или втором, но не в обоих). Оператор:
^или методsymmetric_difference().
Пример:
s_1 = {1, 2, 3}
s_2 = {3, 4, 5}
s_sym_dif = s_1 ^ s_2
# s_sym_dif = s_1.symmetric_difference(s_2)
print(s_sym_dif)
Вывод программы:
{1, 2, 4, 5}
Пример: найти гласные в слове
Множества удобно использовать для фильтрации данных. Например, можно найти, какие гласные буквы встречаются в слове:
vowels = {"а", "е", "ё", "и", "о", "у", "ы", "э", "ю", "я"}
letters = set("коллекция")
print(", ".join(letters & vowels))
Вывод программы:
о, я, и, е
Сравнение множеств
В Python можно сравнивать множества — это удобно для анализа подмножеств, совпадений и включений. Вот основные операции:
- Проверяет, содержат ли два множества одни и те же элементы, независимо от порядка. Оператор:
==.
s_1 = {1, 2, 3}
s_2 = {3, 1, 2}
print(s_1 == s_2)
Вывод программы:
True
- Проверяет, входят ли все элементы одного множества в другое. Оператор:
<=.
s_1 = {1, 2, 3}
s_2 = {1, 2, 3, 4}
print(s_1 <= s_2)
Вывод программы:
True
Проверяет, содержит ли множество все элементы другого множества. Оператор: >=.
s_1 = {1, 2, 3, 4}
s_2 = {1, 2, 3}
print(s_1 >= s_2)
Вывод программы:
True
Методы, изменяющие множество
Множества — изменяемый тип данных. В следующей таблице приведены методы, которые позволяют добавлять, удалять и очищать элементы. Они изменяют множество напрямую.
set.add(e)
Описание
Добавить элемент во множество
Пример:
s = set()
s.add(1)
print(s)
Вывод:
{1}
set.remove(e)
Описание
Удалить элемент множества. Возвращает исключение KeyError, если элемент не принадлежит множеству
Пример:
s = {1, 2, 3}
s.remove(2)
print(s)
Результат:
{1, 3}
set.discard(e)
Описание
Удалить элемент, если он принадлежит множеству
Пример:
s = {1, 2, 3}
s.discard(2)
print(s)
Вывод:
{1, 3}
set.pop()
Описание
Вернуть и удалить произвольный элемент множества
Пример:
s = {1, 2, 3}
x = s.pop()
print(x)
print(s)
Вывод:
2
{1, 3}
set.clear()
Описание
Очистить множество, удалив все его элементы
Пример:
s = {1, 2, 3}
s.clear()
print(s)
Вывод:
set()
Словари (dict)
До этого мы работали с коллекциями, где данные упорядочены и к ним можно обращаться по индексу. Но что, если нужно находить значение не по номеру, а, например, по названию?
В таких случаях пригодится словарь — коллекция, в которой каждому значению сопоставляется ключ. Это позволяет быстро получать доступ к нужной информации по понятному и уникальному идентификатору.
Когда списков недостаточно
Допустим, нам нужно сохранить информацию о странах и их столицах. Один из способов — использовать список кортежей, где каждая пара содержит страну и её столицу:
countries_and_capitals = [("Россия", "Москва"), ("США", "Вашингтон"), ("Франция", "Париж")]
Если мы хотим узнать столицу Франции, придётся пройтись по списку и найти нужную строку:
countries_and_capitals = [("Россия", "Москва"), ("США", "Вашингтон"), ("Франция", "Париж")]
for country in countries_and_capitals:
if country[0] == "Франция":
print(country[1])
break
Этот подход работает, но он не самый удобный — особенно при большом объёме данных.
Как устроен словарь
Словарь (dict) — это коллекция пар ключ: значение. Ключ может быть, например, названием страны, а значение — её столицей.
countries_and_capitals = {"Россия": "Москва",
"США": "Вашингтон",
"Франция": "Париж"}
print(countries_and_capitals["Франция"])
Ключи и значения разделяются двоеточием, пары записываются в фигурных скобках и разделяются запятыми.Ключами могут быть неизменяемые типы данных: строки, числа, кортежи.Значения могут быть любого типа.
Добавление и изменение значений
Чтобы взять значение по ключу, необходимо указать этот ключ в квадратных скобках после имени словаря:
Если же нужно добавить новый ключ в словарь, то его указывают после имени словаря в левой части операции присваивания, а значение, которое будет храниться по этому ключу, — в правой части:
countries_and_capitals = {"Россия": "Москва",
"США": "Вашингтон",
"Франция": "Париж"}
countries_and_capitals["Сербия"] = "Белград"
print(countries_and_capitals)
Примечание
При записи значения по уже существующему ключу, старое значение стирается, и ключ создаётся заново с новым значением.
d = {"key": "old_value"}
d["key"] = "new_value"
print(d["key"])
Вывод программы:
new_value
Обработка ошибок и проверка ключа
Если попытаться получить значение по несуществующему ключу, программа завершится с ошибкой KeyError:
countries_and_capitals = {"Россия": "Москва",
"США": "Вашингтон",
"Франция": "Париж"}
print(countries_and_capitals["Сербия"])
Вывод программы:
KeyError: 'Сербия'
Чтобы избежать этой ошибки, перед обращением к значению словаря стоит проверить, существует ли ключ. Для этого используется уже знакомый нам оператор in:
countries_and_capitals = {"Россия": "Москва",
"США": "Вашингтон",
"Франция": "Париж"}
if "Сербия" in countries_and_capitals:
print(countries_and_capitals["Сербия"])
else:
print("Страна пока не добавлена в словарь")
Перебор словаря в цикле
Пройтись по всем ключам словаря можно с помощью цикла for. При этом на каждой итерации переменная цикла принимает ключ, а значение можно получить по этому ключу:
countries_and_capitals = {"Россия": "Москва",
"США": "Вашингтон",
"Франция": "Париж"}
for country in countries_and_capitals:
print(f"У страны {country} столица — {countries_and_capitals[country]}.")
Вывод программы:
У страны Россия столица — Москва.
У страны США столица — Вашингтон.
У страны Франция столица — Париж.
Значения-коллекции: пример с индексами строк
Значением в словаре может быть не только число или строка, но и коллекция — например, список. Это позволяет хранить по ключу сразу несколько связанных значений.
Рассмотрим пример: пользователь вводит названия стран построчно. Некоторые страны могут повторяться. Нужно сохранить, в каких строках (начиная с нулевой) встречалась каждая страна. Для этого создадим словарь, где ключ — это название страны, а значение — список номеров строк:
# создаём пустой словарь
countries = dict()
# вводим первую строку до цикла (можно заменить, использовав оператор-морж)
country = input()
# создаём счётчик номеров строк
str_number = 0
# продолжаем цикл, пока не введена строка «СТОП»
while country != "СТОП":
# если введённой страны нет в словаре, создаём ключ и записываем по ключу список из одного номера строки
if country not in countries:
countries[country] = [str_number]
# иначе добавляем в список по ключу новое значение номера строки
else:
countries[country].append(str_number)
# увеличиваем счётчик
str_number += 1
# вводим следующую строку
country = input()
# выводим название страны и полученные списки с новой строки
for country in countries:
print(f"{country}: {countries[country]}")
Пример ввода:
США
США
Россия
Россия
Россия
Франция
Сербия
СТОП
Вывод программы:
США: [0, 1]
Россия: [2, 3, 4]
Франция: [5]
Сербия: [6]
Методы словаря
Словари поддерживают множество операций: добавление и удаление элементов, получение значений с запасным вариантом, перебор ключей и значений. Некоторые методы изменяют словарь, другие — только возвращают данные.
В следующей таблице перечислены основные операции и методы, которые чаще всего используются при работе со словарями. Они пригодятся как в учебных задачах, так и в реальных проектах.
len(d)
Описание
Возвращает количество ключей в словаре
Пример:
d = {"a": 1, "b": 2, "c": 3}
print(len(d))
Вывод:
3
del d[key]
Описание
Удалить ключ из словаря. Если ключа нет, то вызывается исключение KeyError
Пример:
d = {"a": 1, "b": 2, "c": 3}
del d["b"]
print(d)
Вывод:
{'a': 1, 'c': 3}
dict.clear()
Описание
Удалить все ключи и значения в словаре
Пример:
d = {"a": 1, "b": 2, "c": 3}
d.clear()
print(d)
Вывод:
{}
dict.get(key, default)
Описание
Возвращает значение по ключу key. Если ключа нет, то возвращает значение default
Пример:
d = {"a": 1, "b": 2, "c": 3}
print(d.get("e", "Ключа нет в словаре"))
Вывод:
Ключа нет в словаре
dict.items()
Описание
Возвращает итерируемый объект, состоящий из кортежей (ключ, значение) словаря
Пример:
d = {"a": 1, "b": 2, "c": 3}
for key, value in d.items():
print(key, value)
Вывод:
a 1
b 2
c 3
dict.keys()
Описание
Возвращает итерируемый объект, состоящий из ключей словаря
Пример:
d = {"a": 1, "b": 2, "c": 3}
for key in d.keys():
print(key)
Вывод:
a
b
c
d.pop(key, default)
Описание
Возвращает значение по ключу key и удаляет его из словаря. Если ключа нет, то возвращает default
Пример:
d = {"a": 1, "b": 2, "c": 3}
x = d.pop("a")
print(x)
Вывод:
1
dict.values()
Описание
Возвращает итерируемый объект, состоящий из значений словаря
Пример:
d = {"a": 1, "b": 2, "c": 3}
for value in d.values():
print(value)
Вывод:
1
2
3
Тот же пример с использованием get()
Ранее мы реализовали программу, которая сохраняет номера строк, в которых встречалась каждая страна. Теперь перепишем её с использованием метода get(). Это позволит сократить код без потери логики.
# создаём пустой словарь
countries = dict()
# вводим первую строку до цикла (можно заменить, использовав оператор-морж)
country = input()
# создаём счётчик номеров строк
str_number = 0
# продолжаем цикл, пока не введена строка «СТОП»
while country != "СТОП":
# Если страна country есть среди ключей, то get() возвращает список,
# хранящийся по этому ключу, иначе get() возвращает пустой список.
# Добавляем в список значение str_number.
countries[country] = countries.get(country, []) + [str_number]
# увеличиваем счётчик
str_number += 1
# вводим следующую строку
country = input()
# выводим название страны и полученные списки с новой строки
for country in countries:
print(f"{country}: {countries[country]}")
Метод get() позволил заменить четыре строчки кода одной. Попробуйте запустить оба варианта программы — вывод будет одинаковым.
Что дальше
Теперь вы умеете работать с неупорядоченными коллекциями: множествами и словарями. Вы знаете, как находить элементы, использовать ключи, удалять и добавлять значения, а также выполнять полезные операции над множествами.
Дальше мы сделаем ещё один шаг вперёд: разберёмся, как быстро создавать и фильтровать списки с помощью списочных выражений, узнаем, что такое генераторы и итераторы, а заодно заглянем «под капот» — и поймём, как Python хранит переменные в памяти.
В следующей статье:
- вы познакомитесь со списочными выражениями (и узнаете, почему они читаются проще, чем
for + append); - научитесь использовать вложенные циклы и условия прямо внутри списков;
- узнаете, как устроены генераторы и почему они экономят память;
- и, наконец, разберётесь, почему у переменных может меняться идентификатор, и что это вообще значит.
Ключевые выводы статьи
- Множество (
set) — неупорядоченная коллекция без повторов; используется для хранения уникальных значений и проверки принадлежности.- Множества поддерживают операции: объединение, пересечение, разность и симметричная разность.
- Словарь (
dict) хранит значения по ключам; ключи должны быть неизменяемыми типами, значения — любыми.- Для безопасного получения значений из словаря используют метод
get()и проверку ключей черезin.- В словарях можно хранить вложенные коллекции и перебирать данные по ключам, значениям или парам.