Словари dict в Python: руководство с примерами

Словари (dict) играют важную роль в Python. В отличие от списков, словари используются для хранения данных в формате ключ -> значение.

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

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

Словарь - это коллекция, которая хранит элементы в виде "ключ": "значение" также известная как ассоциативный массив. Он схож по своему применению с списками, но есть определенные различия:

  1. Ключом может быть все, что угодно: от обычной строки до сложных объектов.
  2. В новых версиях Python (>= 3.7) элементы будут храниться отсортированными по ключу в порядке добавления.
Иллюстрация словаря dict

Как создать словарь

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

ages = {"Юра": 18, "Маша": 22, "Паша": 30}

print(ages)

Вывод:

{'Юра': 18, 'Маша': 22, 'Паша': 30}

Есть второй способ: мы можем использовать конструктор dict:

translations = dict(hello="привет", world="мир")

print(translations)

Вывод:

{'hello': 'привет', 'world': 'мир'}

В Python можно использовать конструктор dict для создания словаря из списка пар “ключ-значение”:

translations = dict([
  ["hello", "привет"],
  ["world", "мир"]
])

print(translations)

Вывод:

{'hello': 'привет', 'world': 'мир'}

Также хочу заметить, Python не позволяет иметь несколько элементов с одинаковым ключом в словаре:

letters = {
  "A": 1,
  "A": 2,
}

print(letters)

Вывод:

{'A': 2}

Как вы можете видеть, "A": 2 перезаписало "A": 1.

Что будет выведено на экран?

dictionary = dict([
    ["apple", "яблоко"],
    ["orange", "апельсин"],
    ["apple", "яблоко-фрукт"]
])

print(dictionary)
{"apple": "яблоко", "orange": "апельсин"}
{"apple": "яблоко-фрукт", "orange": "апельсин"}
{"apple": "яблоко-фрукт", "orange": "апельсин"}
{"apple": "яблоко", "orange": "апельсин", "apple": "яблоко-фрукт"}

Список словарей

Поскольку словарь dict - это просто значение в Python, мы можем хранить словари в других коллекциях. Например, мы можем создать список словарей:

dictionaries = [
  {"привет": "hello", "мир": "world"},
  {"A": 1, "B": 2, "C": 3},
]

print(dictionaries)

Вывод:

[{'привет': 'hello', 'мир': 'world'}, {'A': 1, 'B': 2, 'C': 3}]

Получить элемент из словаря

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

letters = {"A": 1, "B": 2, "C": 3}

print(letters["B"]) # 2
print(letters["C"]) # 3

Но если мы попробуем обратиться к элементу, которого не существует, мы получим ошибку:

empty_dict = {}

print(empty_dict["нет ключа"])

Ошибка:

Traceback (most recent call last):
  ...
KeyError: 'нет ключа'

Чтобы не возникала ошибка при обращении к несуществующему ключу, нужно использовать метод dict.get():

names = {"Андрей": "Andrew", "Макс": "Max"}

print("Дима:", names.get("Дима"))

Вывод:

Дима: None

Как вы можете видеть, метод get() вернул None, поскольку имени "Дима" в словаре нету.

Количество элементов в словаре

Чтобы получить количество элементов в словаре, можно воспользоваться стандартной функцией len():

letters = {"A": 1, "B": 2, "C": 3}
print("количество букв:", len(letters))

Вывод:

количество букв: 3

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

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

lang = {"C++": "static", "Rascal": "unknown"}

lang["Python"] = "dynamic"
lang["Rascal"] = "hybrid"

print(lang)

Вывод:

{'C++': 'static', 'Rascal': 'hybrid', 'Python': 'dynamic'}

Что будет выведено на экран?

fruits = {"apple": "red", "banana": "yellow"}

fruits["mango"] = "yellow"
fruits["banana"] = "green"

print(fruits)
{'apple': 'red', 'banana': 'yellow', 'mango': 'yellow'}
{'apple': 'red', 'banana': 'green', 'mango': 'green'}
{'apple': 'red', 'banana': 'green', 'mango': 'yellow'}
{'apple': 'red', 'banana': 'yellow'}

Чтобы добавить или поменять сразу несколько элементов в словаре, можно использовать метод dict.update():

lang = {"C++": "static", "Rascal": "unknown"}

lang.update(Python="dynamic", Rascal="hybrid")

print(lang)

Вывод совпадает с предыдущим:

{'C++': 'static', 'Rascal': 'hybrid', 'Python': 'dynamic'}

В метод update можно передать другой словарь.

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

first_seen = {"Дима": "вчера"}

first_seen.setdefault("Дима", "сегодня")
first_seen.setdefault("Маша", "сегодня")

print(first_seen)

Вывод:

{'Дима': 'вчера', 'Маша': 'сегодня'}

Как вы можете видеть, setdefault добавил элемент с ключом "Маша", не поменяв существующий с ключом "Дима".

Удалить элемент из словаря

Python поддерживает несколько способов удалить элемент из словаря.

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

population = {"Москва": 12_000_000, "Абракадабра": 0}

del population["Абракадабра"]

print(population)

Вывод:

{'Москва': 12000000}

У типа dict есть специальный метод pop, который можно использовать вместо del:

population = {"Москва": 12_000_000, "Абракадабра": 0}

value = population.pop("Абракадабра")

print(value)
print(population)

Вывод:

0
{'Москва': 12000000}

Метод pop() поддерживает значение по умолчанию и вернет его, если элемент с данным ключом не найден:

empty = {}
print(empty.pop("key", "default value")) # вывод: default value

Если нам нужно удалить все элементы из словаря, то мы можем использовать метод dict.clear():

letters = {"A": 1, "B": 2}
letters.clear()
print(letters)

Вывод:

{}

Метод dict.popitem() удаляет последний добавленный элемент в словаре:

letters = {"B": 2}
letters["A"] = 1
letter = letters.popitem()

print("removed:", letter)
print("all:", letters)

Вывод:

removed: ('A', 1)
all: {'B': 2}

До версии Python 3.7, popitem удалял случайный элемент из словаря.

Перебор элементов словаря

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

students = {"Женя": 20, "Катя": 30, "Марк": 40}
for name in students:
    print(name, students[name])

Вывод:

Женя 20
Катя 30
Марк 40

Метод dict.keys()

Метод keys() позволяет получить все ключи, которые хранятся в словаре:

students = {"Женя": 20, "Катя": 30, "Марк": 40}
for name in students.keys():
    print(name)

Вывод:

Женя
Катя
Марк

По умолчанию, цикл for перебирает именно ключи словаря.

Метод dict.values()

Чтобы вместо ключей получить значения, используйте метод values():

students = {"Женя": 20, "Катя": 30, "Марк": 40}
for age in students.values():
    print(age)

Вывод:

20
30
40

Метод dict.items()

Часто бывает удобно получить сразу ключ вместе со значением при переборе словаря. Тут метод items() приходится как нельзя кстати:

students = {"Женя": 20, "Катя": 30, "Марк": 40}
for name, age in students.items():
    print(name, age)

Вывод:

Женя 20
Катя 30
Марк 40

Словарь со словарями

Вложенные словари

Поскольку словари в Python могут хранить любые значения, нам ничего не мешает создать словарь словарей:

game = {
    "влево": {
        "влево": "пусто",
        "вправо": "приз!",
    },
    "вправо": {
        "влево": "пусто",
        "вправо": "поощрительный приз",
    },
}

print(game["влево"]["вправо"]) # приз!
print(game["вправо"]["вправо"]) # поощрительный приз

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

Проверить наличие ключа в словаре

Часто возникает необходимость выполнить код в зависимости от наличия определенного ключа в словаре. Ключевое слово in позволяет сделать именно это:

country = {"name": "Франция", "population": 67_000_000}
if "name" in country:
    print("Страна:", country["name"])
else:
    print("Страна без названия")

Вывод:

Страна: Франция

Как скопировать словарь

В Python есть специальный метод для копирования словарей - copy():

original = {"A": 1, "B": 2}
copy = original.copy()
copy["C"] = 3

print("original:", original)
print("copy:    ", copy)

Вывод:

original: {'A': 1, 'B': 2}
copy:     {'A': 1, 'B': 2, 'C': 3}

Если по каким-то причинам вы не хотите использовать метод copy(), то вы можете создать новый словарь при помощи конструктора dict:

original = {"A": 1, "B": 2}

copy = dict(original) # конструктор вместо метода copy

copy["C"] = 3

print("original:", original)
print("copy:    ", copy)

Вывод не поменялся:

original: {'A': 1, 'B': 2}
copy:     {'A': 1, 'B': 2, 'C': 3}

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

Python позволяет создавать словари на основе различных данных с использованием механизма генераторов:

sqr = {x: x * x for x in range(1, 4)}

print(sqr)

Вывод:

{1: 1, 2: 4, 3: 9}

Как и в случае генераторов для списков, мы можем использовать if для фильтрации элементов в словаре:

sqr = {x: x * x for x in range(1, 8) if x % 2 == 0}

print(sqr)

Вывод:

{2: 4, 4: 16, 6: 36}

Какой будет вывод следующего Python кода?

items = {"a": 1, "b": 2, "c": 3}
doubled = {k: v * 2 for k, v in items.items() if v % 2 != 0}

print(doubled)
{"a": 2, "b": 4, "c": 6}
{"a": 2, "c": 6}
{"b": 4, "c": 6}
{"a": 1, "b": 4, "c": 6}

Функция type для словарей

Если вам требуется убедиться, что переменная содержит словарь, то вы можете воспользоваться функцией type:

number = 1
d = {1: 2, 2: 3}

print("number is a dict:", type(number) == dict)
print("d is a dict:     ", type(d) == dict)

Вывод:

number is a dict: False
d is a dict:      True

Упражнения

  1. Создание базового словаря:
    Напишите программу на Python, которая позволяет пользователю вводить пары ключ -> значение и сохраняет их в словарь. После того как пользователь завершит ввод, программа должна выводить весь словарь.
  2. Поиск по ключу:
    Реализуйте функционал, который позволит пользователю вводить ключ, а программа будет возвращать соответствующее значение из словаря. Если такого ключа нет - выводите соответствующее сообщение.
  3. Добавление и удаление элементов:
    Расширьте вашу программу так, чтобы пользователь мог добавлять новые пары ключ -> значение или удалять существующие по ключу. После каждого изменения, выводите обновленный словарь на экран.

Обсуждение