W3docs

Словари Python

Словари Python: создание, доступ, обновление, удаление, перебор и генераторы — с примерами и разбором типичных ошибок.

Словарь Python — это изменяемая упорядоченная коллекция пар ключ-значение. В отличие от списков или кортежей (которые используют целочисленные позиции), словарь позволяет пометить каждое значение понятным ключом — это делает поиск быстрым, а код — более читаемым. Словари — один из наиболее используемых встроенных типов Python и основа для работы с JSON, управления конфигурацией, подсчёта слов и многого другого.

В этой главе рассмотрено всё необходимое для уверенной работы со словарями: создание, доступ к элементам, изменение, удаление, перебор, генераторы и типичные ошибки.

Связанные главы: Методы словарей | Вложенные словари | Перебор словарей | Копирование словарей | Генераторы Python

Что такое словарь?

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

# string keys → integer values
inventory = {'apple': 10, 'banana': 5, 'orange': 8}

# mixed value types are fine
person = {'name': 'Alice', 'age': 30, 'active': True}

# tuple keys work because tuples are immutable
grid = {(0, 0): 'origin', (1, 0): 'east', (0, 1): 'north'}

Начиная с Python 3.7 словари сохраняют порядок вставки — при переборе ключи всегда возвращаются в том порядке, в котором были добавлены.

Создание словаря

Литерал в фигурных скобках

Самый распространённый способ: пары ключ-значение разделяются запятыми, между ключом и значением ставится двоеточие, весь литерал заключается в {}.

config = {'host': 'localhost', 'port': 5432, 'debug': True}
print(config)
# {'host': 'localhost', 'port': 5432, 'debug': True}

Пустой словарь — просто {}.

empty = {}
print(type(empty))  # <class 'dict'>

Конструктор dict()

Передайте именованные аргументы в dict(), когда ключи являются допустимыми идентификаторами Python:

config = dict(host='localhost', port=5432, debug=True)
print(config)
# {'host': 'localhost', 'port': 5432, 'debug': True}

Можно также передать итерируемый объект из двухэлементных последовательностей:

pairs = [('x', 10), ('y', 20)]
point = dict(pairs)
print(point)  # {'x': 10, 'y': 20}

dict.fromkeys()

Создание словаря из списка ключей, которым присваивается одно общее начальное значение:

defaults = dict.fromkeys(['timeout', 'retries', 'verbose'], 0)
print(defaults)
# {'timeout': 0, 'retries': 0, 'verbose': 0}

Важно: если значением по умолчанию является изменяемый объект (например, список), все ключи будут ссылаться на один и тот же объект. Вместо этого используйте генератор словаря (см. ниже).

Генератор словаря

Лаконичный способ построить словарь из любого итерируемого объекта:

squares = {x: x ** 2 for x in range(1, 6)}
print(squares)
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Полный синтаксис см. в Генераторы Python.

Доступ к значениям

Доступ через квадратные скобки

inventory = {'apple': 10, 'banana': 5, 'orange': 8}
print(inventory['apple'])   # 10

Если ключ не существует, Python вызывает KeyError:

try:
    print(inventory['grape'])
except KeyError as e:
    print(f'KeyError: {e}')   # KeyError: 'grape'

get() — безопасный доступ со значением по умолчанию

dict.get(key, default) возвращает значение, если ключ существует, или default (по умолчанию None) — без вызова исключения.

print(inventory.get('grape'))       # None
print(inventory.get('grape', 0))    # 0
print(inventory.get('apple', 0))    # 10

Используйте .get(), когда не уверены в наличии ключа. Используйте доступ через квадратные скобки, когда ключ обязан быть — отсутствие ключа в этом случае является настоящей ошибкой, которая должна проявляться как исключение.

Проверка существования ключа

print('apple' in inventory)    # True
print('grape' in inventory)    # False
print('grape' not in inventory) # True

in проверяет ключи, а не значения. Работает за O(1) в среднем — постоянное время, независимо от размера словаря.

Добавление и обновление элементов

Добавление новой пары ключ-значение

Присвоение значения несуществующему ключу:

inventory['grape'] = 12
print(inventory)
# {'apple': 10, 'banana': 5, 'orange': 8, 'grape': 12}

Обновление существующего значения

Присвоение значения уже существующему ключу — старое значение заменяется:

inventory['apple'] = 15
print(inventory['apple'])  # 15

update() — массовое добавление или перезапись

Передайте другой словарь или итерируемый объект с парами ключ-значение:

inventory.update({'banana': 7, 'mango': 3})
print(inventory)
# {'apple': 15, 'banana': 7, 'orange': 8, 'grape': 12, 'mango': 3}

Слияние с | (Python 3.9+)

Оператор | создаёт новый объединённый словарь. Если ключ присутствует в обоих, побеждает правый операнд:

a = {'x': 1, 'y': 2}
b = {'y': 99, 'z': 3}
merged = a | b
print(merged)   # {'x': 1, 'y': 99, 'z': 3}

Используйте |=, чтобы слить b в a на месте — аналог a.update(b), но нагляднее.

setdefault() — вставка только при отсутствии ключа

dict.setdefault(key, default) вставляет ключ со значением по умолчанию, если его нет, а затем всегда возвращает значение для этого ключа. Это эффективнее конструкции if key not in d: d[key] = default.

scores = {'Alice': 95}
scores.setdefault('Bob', 0)     # Bob absent → inserts 0, returns 0
scores.setdefault('Alice', 0)   # Alice present → does nothing, returns 95
print(scores)   # {'Alice': 95, 'Bob': 0}

Классический пример использования — группировка элементов:

words = ['cat', 'car', 'bus', 'can', 'bat']
groups = {}
for word in words:
    groups.setdefault(word[0], []).append(word)
print(groups)
# {'c': ['cat', 'car', 'can'], 'b': ['bus', 'bat']}

Удаление элементов

del — удаление по ключу

inventory = {'apple': 15, 'banana': 7, 'orange': 8, 'grape': 12}
del inventory['orange']
print(inventory)
# {'apple': 15, 'banana': 7, 'grape': 12}

del вызывает KeyError, если ключ отсутствует. Чтобы этого избежать, сначала проверьте через in или используйте pop() со значением по умолчанию.

pop() — удаление с возвратом значения

removed = inventory.pop('grape')
print(removed)      # 12
print(inventory)    # {'apple': 15, 'banana': 7}

Передайте второй аргумент, чтобы избежать KeyError при возможном отсутствии ключа:

val = inventory.pop('pear', 'not found')
print(val)   # not found

popitem() — удаление последнего добавленного элемента (Python 3.7+)

d = {'a': 1, 'b': 2, 'c': 3}
last = d.popitem()
print(last)   # ('c', 3)
print(d)      # {'a': 1, 'b': 2}

clear() — удаление всех элементов

d = {'a': 1, 'b': 2}
d.clear()
print(d)   # {}

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

Три представления позволяют перебирать разные части словаря. Все три являются живыми — они отражают изменения в словаре без необходимости пересоздания.

Ключи (итерация по умолчанию)

Прямой перебор словаря возвращает его ключи:

person = {'name': 'Alice', 'age': 30, 'city': 'Paris'}

for key in person:
    print(key)
# name
# age
# city

person.keys() возвращает те же ключи в виде явного объекта-представления dict_keys.

Значения

for val in person.values():
    print(val)
# Alice
# 30
# Paris

Пары ключ-значение

for key, val in person.items():
    print(f'{key}: {val}')
# name: Alice
# age: 30
# city: Paris

.items() — наиболее распространённый выбор, когда внутри цикла нужны и ключ, и значение. Дополнительные шаблоны см. в Перебор словарей.

Представления являются живыми

d = {'a': 1}
keys_view = d.keys()
d['b'] = 2
print(keys_view)   # dict_keys(['a', 'b'])  ← reflects the new key

Генераторы словарей

Генераторы словарей позволяют строить или преобразовывать словари в одном читаемом выражении.

Фильтрация по значению

inventory = {'apple': 15, 'banana': 7, 'orange': 8, 'grape': 12, 'mango': 3}
popular = {k: v for k, v in inventory.items() if v >= 8}
print(popular)
# {'apple': 15, 'orange': 8, 'grape': 12}

Инвертирование словаря (замена ключей и значений)

original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}
print(swapped)   # {1: 'a', 2: 'b', 3: 'c'}

Это работает корректно только при условии уникальности всех значений.

Счётчик частоты слов

sentence = 'the quick brown fox jumps over the lazy dog'
freq = {}
for word in sentence.split():
    freq[word] = freq.get(word, 0) + 1
print(freq)
# {'the': 2, 'quick': 1, 'brown': 1, 'fox': 1, ...}

Полезные встроенные функции

ОперацияПримерРезультат
Длинаlen(inventory)количество пар ключ-значение
Копия (поверхностная)inventory.copy()новый словарь с теми же ссылками
Преобразовать в список ключейlist(inventory)['apple', 'banana', ...]
Отсортированные ключиsorted(inventory)['apple', 'banana', ...] по алфавиту
Все значения истинны?all(inventory.values())True / False
Хотя бы одно значение истинно?any(inventory.values())True / False

Полный справочник по всем методам словаря (copy, fromkeys, update, setdefault, popitem и другим) см. в Методы словарей Python.

Типичные ошибки

1. KeyError при отсутствующем ключе — всегда используйте .get() или in, если ключ может отсутствовать.

2. Нехешируемые типы ключей — списки не могут быть ключами словаря, поскольку они изменяемы. Используйте кортеж:

# This raises TypeError: unhashable type: 'list'
# bad = {[1, 2]: 'value'}

# Use a tuple:
coords = {(1, 2): 'A', (3, 4): 'B'}
print(coords[(1, 2)])  # A

3. Изменение во время перебора — добавление или удаление ключей во время цикла по словарю вызывает RuntimeError. Сначала сделайте снимок:

d = {'a': 1, 'b': 2, 'c': 3}
for key in list(d):          # list() copies the keys
    if d[key] < 2:
        del d[key]
print(d)   # {'b': 2, 'c': 3}

4. Поверхностная копия против глубокойdict.copy() и {**d} выполняют поверхностное копирование. Вложенные изменяемые значения (списки, словари) по-прежнему остаются общими. Используйте copy.deepcopy(), когда нужны полностью независимые копии. См. Копирование словарей.

Словари против других типов коллекций

Характеристикаdictlisttupleset
УпорядоченДа (3.7+)ДаДаНет
ИзменяемыйДаДаНетДа
Индексируется поКлючуЦелому числуЦелому числу
ДубликатыКлючи: нет; Значения: даДаДаНет
Основное применениеСопоставление ключ-значениеУпорядоченная последовательностьНеизменяемая последовательностьУникальность / операции над множествами

Когда нужно найти что-то по осмысленному метке, а не по позиции, словарь — почти всегда правильный выбор. Для упорядоченных уникальных значений рассмотрите множество. Для простой упорядоченной последовательности используйте список.

Практика

Практика
What is true about Python dictionaries according to the information given in the article?
What is true about Python dictionaries according to the information given in the article?
Was this page helpful?