Глиф Учебники

Урок 9. Словари и множества

Курс «Python» · урок 9 из 10 · 3 минуты чтения

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

Словарь

Словарь (dict) хранит пары ключ: значение в фигурных скобках. По ключу значение находится сразу, без перебора:

Python
capitals = {"Беларусь": "Минск", "Польша": "Варшава", "Литва": "Вильнюс"}
print(capitals["Беларусь"])
capitals["Латвия"] = "Рига"
print(len(capitals))
print("Литва" in capitals)
print(capitals.get("Франция", "неизвестно"))
Вывод
Минск
4
True
неизвестно

Если взять через квадратные скобки ключ, которого нет, программа остановится с ошибкой KeyError: 'Франция'. get такой ошибки не даёт: без второго аргумента он возвращает None.

capitals ключ значение "Беларусь" "Минск" "Польша" "Варшава" "Литва" "Вильнюс" capitals["Беларусь"] "Минск" значение по ключу capitals["Франция"] KeyError такого ключа нет capitals.get("Франция", "неизвестно") "неизвестно" запасное
Словарь capitals хранит пары ключ → значение: по ключу «Беларусь» сразу находится «Минск», а ключа «Франция» нет — квадратные скобки дают KeyError, а get возвращает запасное значение.

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

Перебор словаря

for по словарю перебирает ключи. Пары целиком даёт метод items(), только значения — values(), только ключи — keys():

Python
fruits = {"яблоки": 5, "груши": 3, "сливы": 12}
for name, count in fruits.items():
    print(name, "—", count)
print(sum(fruits.values()))
print(list(fruits.keys()))
Вывод
яблоки — 5
груши — 3
сливы — 12
20
['яблоки', 'груши', 'сливы']

Пары перебираются в том порядке, в котором добавлялись.

Изменение и удаление

Python
stock = {"хлеб": 10, "молоко": 4}
stock["хлеб"] -= 3
stock["сыр"] = 2
del stock["молоко"]
print(stock)
removed = stock.pop("сыр")
print(removed, stock)
Вывод
{'хлеб': 7, 'сыр': 2}
2 {'хлеб': 7}

del d[ключ] удаляет пару, d.pop(ключ) удаляет и возвращает значение.

Частый приём: подсчёт

Сколько раз встречается каждое слово? Ключ — слово, значение — счётчик. get(word, 0) даёт 0 для слова, которое встретилось впервые:

Python
text = "мама мыла раму мама"
counts = {}
for word in text.split():
    counts[word] = counts.get(word, 0) + 1
print(counts)
for word in sorted(counts):
    print(word, counts[word])
Вывод
{'мама': 2, 'мыла': 1, 'раму': 1}
мама 2
мыла 1
раму 1
слово counts после шага counts.get(word, 0) + 1 мама мама: 1 0 + 1 новое слово мыла мама: 1 мыла: 1 0 + 1 новое слово раму мама: 1 мыла: 1 раму: 1 0 + 1 новое слово мама мама: 2 мыла: 1 раму: 1 1 + 1 уже было
Подсчёт по шагам: для нового слова counts.get(word, 0) даёт 0, и счётчик становится 1, а второе «мама» увеличивает свой счётчик до 2.

sorted(counts) даёт ключи словаря по алфавиту. Для подсчёта есть и готовое средство — Counter из модуля collections, но устроен он так же.

Множество

Множество (set) хранит значения без повторов и без порядка. Из списка с повторами оно оставляет каждое значение по одному разу:

Python
nums = [3, 1, 3, 2, 1, 3]
unique = set(nums)
print(len(unique))
print(sorted(unique))
print(2 in unique)
Вывод
3
[1, 2, 3]
True

Порядок элементов в множестве не гарантирован. Если результат нужно вывести по порядку, его сортируют: sorted(s).

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

ЗаписьРезультат
a | bобъединение: всё, что есть хотя бы в одном
a & bпересечение: то, что есть в обоих
a - bразность: то, что есть в a, но нет в b
a ^ bто, что есть ровно в одном из двух
Python
a = {1, 2, 3, 4}
b = {3, 4, 5}
print(sorted(a | b))
print(sorted(a & b))
print(sorted(a - b))
print(sorted(a ^ b))
Вывод
[1, 2, 3, 4, 5]
[3, 4]
[1, 2]
[1, 2, 5]
a = {1, 2, 3, 4} b = {3, 4, 5} a b 1 2 3 4 5 a | b {1, 2, 3, 4, 5} объединение a b 1 2 3 4 5 a & b {3, 4} пересечение a b 1 2 3 4 5 a - b {1, 2} разность a b 1 2 3 4 5 a ^ b {1, 2, 5} ровно в одном
Для a = {1, 2, 3, 4} и b = {3, 4, 5}: a | b — всё из обоих множеств, a & b — общее, a - b — только то, что есть в a, a ^ b — то, что есть ровно в одном из них.

Пример — сколько разных слов во фразе без учёта регистра:

Python
text = input()
words = set(text.lower().split())
print(len(words))
Ввод
Кот и пёс и кот
Вывод
3

Кортеж

Ещё один набор значений — кортеж (tuple): как список, только в круглых скобках и неизменяемый. (3, 4) — кортеж из двух чисел. Кортеж возвращает функция с return a, b, кортежем может быть ключ словаря: например, координаты клетки (строка, столбец).

Что выбрать

ЗадачаЧто взять
значения по порядку, с повторами, доступ по номерусписок []
значение по названию: страна → столицасловарь {ключ: значение}
только уникальные значения, быстрая проверка inмножество set()
неизменяемый набор, ключ словарякортеж ()

Коротко

Проверьте себя

1. Что выведет программа?
Python
d = {"a": 1, "b": 2}
d["a"] = 5
d["c"] = 3
print(len(d), d["a"])
2. Как получить значение по ключу так, чтобы при отсутствии ключа не было ошибки?
3. Что выведет print(len(set([1, 1, 2, 2, 2, 3])))?
4. Что создаёт запись x = {}?