</>
Topic 13 of 18

Course materials are currently available in Russian only.

Словари

selfedu · The video is optional — everything you need is in the text below.Open on YouTube ↗

Список хранит значения по номерам: a[0], a[1], … А что если удобнее искать не по номеру, а по названию: цена по имени товара, телефон по имени человека, количество по слову? Для этого есть словари.

Словарь: ключ → значение

prices = {"хлеб": 45, "молоко": 89, "сыр": 320}
print(prices["молоко"])     # 89

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

Добавить или изменить значение:

prices["чай"] = 150         # новый ключ — пара добавится
prices["хлеб"] = 50         # существующий — значение заменится
print(len(prices))          # 4

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

Нет такого ключа

Обращение к отсутствующему ключу — ошибка KeyError:

print(prices["кофе"])       # KeyError

Варианты:

if "кофе" in prices:        # проверка ключа
    print(prices["кофе"])

print(prices.get("кофе"))       # None — ключа нет
print(prices.get("кофе", 0))    # 0 — своё значение по умолчанию

Удалить ключ: del prices["сыр"] или prices.pop("сыр").

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

ages = {"Аня": 12, "Боря": 14, "Вика": 13}

for name in ages:                 # перебираются ключи
    print(name)

for name, age in ages.items():    # пары ключ-значение
    print(name, age)

print(list(ages.values()))        # [12, 14, 13]
print(sorted(ages))               # ключи по алфавиту

Словарь помнит порядок, в котором добавлялись ключи. Если нужен другой порядок — сортируй.

Подсчёт частот

Самое частое применение словаря — посчитать, сколько раз встречается каждое значение:

words = "кот пёс кот рыба пёс кот".split()
count = {}
for w in words:
    count[w] = count.get(w, 0) + 1
print(count)    # {'кот': 3, 'пёс': 2, 'рыба': 1}

count.get(w, 0) возвращает текущее число или 0, если слово встретилось впервые.

Ключ с наибольшим значением можно найти обычным перебором или через max(count, key=count.get) — но помни, что при равенстве max вернёт первый такой ключ в порядке словаря.

Counter

Для подсчёта есть готовый инструмент:

from collections import Counter
c = Counter("abracadabra")
print(c["a"])               # 5
print(c.most_common(2))     # [('a', 5), ('b', 2)]

Группировка

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

words = ["арбуз", "банан", "абрикос", "брусника", "вишня"]
by_letter = {}
for w in words:
    first = w[0]
    if first not in by_letter:
        by_letter[first] = []
    by_letter[first].append(w)
print(by_letter["б"])     # ['банан', 'брусника']

Ключом может быть любое неизменяемое значение: число, строка, кортеж. Например, координаты (x, y) — хороший ключ, а список — нет. Если нужно сгруппировать по «набору» значений, превращай его в строку или кортеж.

Словарь вместо длинного if

days = {1: "пн", 2: "вт", 3: "ср", 4: "чт", 5: "пт", 6: "сб", 7: "вс"}
n = int(input())
print(days.get(n, "нет такого дня"))

Итог

  • словарь — пары ключ: значение, доступ d[ключ] работает мгновенно;
  • запись по существующему ключу заменяет значение;
  • in, get(ключ, по_умолчанию) защищают от KeyError;
  • items(), keys(), values() — перебор;
  • d[x] = d.get(x, 0) + 1 — подсчёт частот; Counter — то же готовое;
  • ключи — только неизменяемые значения: числа, строки, кортежи.