Создание
a = {"name": "Anna", "age": 25}b = dict(name="Anna", age=25)c = dict([("a", 1), ("b", 2)])d = dict(zip(["x", "y"], [1, 2]))e = dict.fromkeys(["a", "b"], 0)f = {k: k ** 2 for k in range(4)}g = {}Начиная с Python 3.7 словарь запоминает порядок вставки.
Требования к ключам
Ключ должен быть хешируемым: int, float, str, bool, tuple из хешируемых элементов, frozenset, а также объекты своих классов (по умолчанию хеш строится от идентификатора). Списки, словари и множества ключами быть не могут.
d = {1: "a", 1.0: "b", True: "c"}print(d)Результат: {1: 'c'} — ключи 1, 1.0 и True равны и имеют одинаковый хеш.
Операции
d = {"a": 1, "b": 2}print(d["a"])print(len(d))print("a" in d)print("z" not in d)d["c"] = 3d["a"] = 10del d["b"]print(d)print(list(d))print(sorted(d))Обращение по отсутствующему ключу вызывает KeyError.
Методы dict
| Метод | Описание |
|---|---|
get(key[, default]) | Значение или default (по умолчанию None) |
setdefault(key[, default]) | Значение; если ключа нет, добавляет default |
pop(key[, default]) | Удаляет ключ и возвращает значение |
popitem() | Удаляет и возвращает последнюю добавленную пару |
update(other) | Добавляет и обновляет пары из словаря или итерируемого |
keys() | Представление ключей |
values() | Представление значений |
items() | Представление пар (ключ, значение) |
clear() | Удаляет все пары |
copy() | Поверхностная копия |
fromkeys(iterable[, value]) | Классовый метод: новый словарь из ключей |
d = {"a": 1, "b": 2}print(d.get("z"))print(d.get("z", 0))print(d.setdefault("c", 3))print(d.pop("a"))print(d.pop("zzz", None))print(d.popitem())d.update({"x": 10, "y": 20})d.update(z=30)print(d)setdefault для группировки
words = ["apple", "avocado", "banana", "blueberry", "cherry"]groups = {}for w in words: groups.setdefault(w[0], []).append(w)print(groups)Представления
keys(), values() и items() возвращают динамические представления: они отражают изменения словаря и ведут себя как множества (keys и items).
a = {"x": 1, "y": 2, "z": 3}b = {"y": 2, "z": 0, "w": 4}print(a.keys() & b.keys())print(a.keys() - b.keys())print(a.keys() | b.keys())print(a.items() & b.items())view = a.keys()a["new"] = 1print(list(view))Перебор
d = {"a": 1, "b": 2}for key in d: print(key)for value in d.values(): print(value)for key, value in d.items(): print(key, value)Менять размер словаря во время перебора нельзя — будет RuntimeError. Перебирайте копию ключей:
d = {"a": 1, "b": 2, "c": 3}for key in list(d): if d[key] % 2: del d[key]print(d)Объединение
a = {"x": 1, "y": 2}b = {"y": 20, "z": 30}print(a | b)print({**a, **b})a |= bprint(a)При совпадении ключей побеждает значение из правого словаря.
Включения
squares = {x: x ** 2 for x in range(5)}even = {k: v for k, v in squares.items() if v % 2 == 0}inverted = {v: k for k, v in squares.items()}print(even)print(inverted)Вложенные структуры
config = { "db": {"host": "localhost", "port": 5432}, "debug": True,}print(config["db"]["port"])print(config.get("cache", {}).get("ttl", 60))Сортировка по значениям
scores = {"a": 3, "b": 1, "c": 2}by_value = dict(sorted(scores.items(), key=lambda kv: kv[1]))print(by_value)top = max(scores, key=scores.get)print(top)Производные классы словарей
Стандартная библиотека содержит специализированные варианты:
from collections import defaultdict, OrderedDict, Counter, ChainMapdd = defaultdict(int)for ch in "hello": dd[ch] += 1print(dict(dd))groups = defaultdict(list)groups["a"].append(1)counter = Counter("hello")print(counter.most_common(1))merged = ChainMap({"a": 1}, {"a": 2, "b": 3})print(merged["a"], merged["b"])Подробнее они описаны в главе про collections.
Класс MappingProxyType
Неизменяемое представление словаря:
from types import MappingProxyTypeoriginal = {"a": 1}proxy = MappingProxyType(original)print(proxy["a"])original["a"] = 2print(proxy["a"])Свой тип-отображение
Для создания собственного словаря наследуйтесь от collections.UserDict:
from collections import UserDictclass LowerDict(UserDict): def __setitem__(self, key, value): super().__setitem__(key.lower(), value)d = LowerDict()d["Name"] = "Anna"print(d)Производительность
- Поиск, вставка и удаление ключа — O(1) в среднем
- Порядок вставки сохраняется
- Словарь занимает больше памяти, чем список: для множества мелких записей рассмотрите
dataclass(slots=True)илиnamedtuple
Задания
- Подсчитайте количество вхождений каждого символа в строку через обычный словарь.
- Инвертируйте словарь так, чтобы для повторяющихся значений получился список ключей.
- Реализуйте LRU-кеш на основе
dictи порядка вставки.
