Словари (dict) в языке Python: от основ до продвинутых техник
Тип dict в Python: основы и варианты использования
Словарь (dict) - это изменяемая коллекция, хранящая пары «ключ-значение». Ключи должны быть хешируемыми (неизменяемыми), значения могут быть любого типа. Начиная с Python 3.7 словарь сохраняет порядок вставки элементов.
Создание словаря с помощью литерала {} - самый распространённый способ:
person = {
"name": "Анна",
"age": 30,
"city": "Москва"
}
print(person)
Python type self (тип self в python)
{'name': 'Анна', 'age': 30, 'city': 'Москва'}
Python typing function (аннотация типа функции в python)
Возможные проблемы:
- Попытка обратиться по отсутствующему ключу вызывает KeyError. Решение: использовать метод get() или проверку in.
- Ключ должен быть хешируемым: нельзя использовать список или другой словарь. Для хранения нехешируемых ключей можно преобразовать их в кортеж.
Как создать словарь с помощью конструктора dict()?
Конструктор dict() позволяет создать словарь из последовательности пар (кортежей или списков) или из именованных аргументов:
# Из списка кортежей
items = [("a", 1), ("b", 2)]
d1 = dict(items)
print(d1)
# Из именованных аргументов
d2 = dict(name="Иван", age=25)
print(d2)
Python 3.12 type (новые возможности типов в python 3.12)
{'a': 1, 'b': 2}
{'name': 'Иван', 'age': 25}
Python typing type checking (проверка типов с помощью typing в python)
Цель:
Используется, когда исходные данные имеют структуру пары или необходимо явно указать имена ключей без кавычек.
Как применить словарное включение (dict comprehension)?
Словарное включение - генерация словаря на лету с помощью выражения {ключ: значение for элемент in последовательность}. Удобно для трансформации данных:
# Квадраты чисел от 1 до 5
squares = {x: x**2 for x in range(1, 6)}
print(squares)
Python type dict (тип dict в python)
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Python return type (тип возврата функции в python)
Типичная ошибка:
Попытка использовать изменяемый ключ (например, список) приведёт к ошибке TypeError: unhashable type.
Как создать словарь со значениями по умолчанию с помощью dict.fromkeys()?
Статический метод fromkeys(iterable, value) создаёт словарь, где каждый элемент из iterable становится ключом, а значение для всех ключей одинаково:
keys = ['a', 'b', 'c']
default_dict = dict.fromkeys(keys, 0)
print(default_dict)
{'a': 0, 'b': 0, 'c': 0}
Цель:
Быстрая инициализация словаря с фиксированным значением, например, для подсчёта или хранения настроек.
Как использовать defaultdict из модуля collections для автоматического создания значений?
defaultdict - подкласс dict, который при обращении к отсутствующему ключу автоматически создаёт запись со значением, возвращаемым фабричной функцией. Полезно для группировки или подсчёта:
from collections import defaultdict
# Счётчик букв в строке
text = "hello"
counter = defaultdict(int)
for ch in text:
counter[ch] += 1
print(dict(counter))
{'h': 1, 'e': 1, 'l': 2, 'o': 1}
Проблема:
При сериализации (json.dumps) defaultdict превращается в обычный dict, но при десериализации не восстанавливается - требуется явное преобразование.
Как объединять два словаря с помощью оператора | и метода update?
Оператор | (Python 3.9+) и |= создают новый словарь, объединяя пары из обоих. Если ключи совпадают, приоритет у правого операнда:
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
d3 = d1 | d2
print(d3)
{'a': 1, 'b': 3, 'c': 4}
Метод update() изменяет исходный словарь, добавляя пары из другого словаря или из итерабельной последовательности:
d1.update({'c': 5})
print(d1)
{'a': 1, 'b': 2, 'c': 5}
Как передавать словарь в функцию с помощью распаковки **?
Распаковка **dict позволяет передавать пары ключ-значение как именованные аргументы:
def greet(name, age):
print(f"{name} is {age} years old")
info = {'name': 'Ольга', 'age': 28}
greet(**info)
Ольга is 28 years old
Цель:
Упрощает вызов функций с динамическими параметрами, считываемыми из конфигурации или пользовательского ввода.
Как указать аннотацию типа для словаря?
Для статической типизации используется Dict[KeyType, ValueType] из модуля typing:
from typing import Dict
# Пустой словарь с аннотацией
config: Dict[str, int] = {}
# Функция, возвращающая словарь
def get_scores() -> Dict[str, float]:
return {'Alice': 95.5, 'Bob': 88.0}
В Python 3.9+ можно использовать встроенные dict[str, int]:
def process(data: dict[str, list[int]]) -> None:
pass
Распространённые ошибки:
- Изменение словаря во время итерации по его ключам может привести к непредсказуемому поведению. Решение: итерироваться по копии list(dict.keys()).
- Неглубокое копирование (copy()) не копирует вложенные объекты. Для полного копирования используется copy.deepcopy().
Расширенные примеры использования словарей
Вложенные словари позволяют моделировать сложные структуры данных, например, базу пользователей:
users = {
'user1': {
'name': 'Екатерина',
'age': 29,
'roles': ['admin', 'editor']
},
'user2': {
'name': 'Дмитрий',
'age': 35,
'roles': ['viewer']
}
}
print(users['user1']['name']) # Екатерина
Екатерина
Группировка элементов по ключу с использованием defaultdict - эффективное решение для обработки последовательностей:
from collections import defaultdict
words = ['apple', 'banana', 'apricot', 'blueberry', 'cherry']
grouped = defaultdict(list)
for word in words:
first_letter = word[0]
grouped[first_letter].append(word)
print(dict(grouped))
{'a': ['apple', 'apricot'], 'b': ['banana', 'blueberry'], 'c': ['cherry']}
Использование словаря для кэширования результатов вычислительных функций (мемоизация):
def fib(n, cache={}):
if n in cache:
return cache[n]
if n < 2:
return n
result = fib(n-1, cache) + fib(n-2, cache)
cache[n] = result
return result
print(fib(10))
print(fib(15))
55 610
Сериализация словаря в JSON и обратно:
import json
data = {'name': 'Тест', 'values': [1, 2, 3], 'nested': {'key': True}}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
{
"name": "Тест",
"values": [1, 2, 3],
"nested": {
"key": true
}
}
Обратное преобразование:
restored = json.loads(json_str)
print(restored == data)
True
Сортировка словаря по значению с получением списка ключей:
scores = {'Alice': 95, 'Bob': 82, 'Charlie': 91}
sorted_names = sorted(scores, key=lambda k: scores[k], reverse=True)
print(sorted_names)
['Alice', 'Charlie', 'Bob']
Слияние двух словарей с суммированием значений при совпадении ключей:
from collections import Counter
a = {'x': 10, 'y': 5}
b = {'x': 3, 'z': 7}
merged = Counter(a) + Counter(b)
print(dict(merged))
{'x': 13, 'y': 5, 'z': 7}
Удаление ключей с пустыми значениями из словаря:
raw = {'a': '', 'b': 0, 'c': None, 'd': 'hello'}
cleaned = {k: v for k, v in raw.items() if v}
print(cleaned)
{'d': 'hello'}
Преобразование списка пар в словарь с проверкой на дубликаты:
pairs = [('a', 1), ('b', 2), ('a', 3)]
result = {}
for k, v in pairs:
if k in result:
raise ValueError(f"Duplicate key: {k}")
result[k] = v
print(result)
ValueError: Duplicate key: a