Словарь (dictionary или dict) — это неупорядоченная (в отличие от списка) структура данных в языке программирования Python, которая имеет вид «ключ — значение».

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

Виктор

+7 905 600 50 40

Юлия

+7 960 540 43 32

Александр

+7 960 830 72 61

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

То есть, если добавить в таблицу выше новый номер (ключ) с именем «Юлия» (значение), то запись не будет дублироваться, а обновится уже существующее значение.

При этом, чтобы узнать номер определенного человека, нужно указать его имя. Таким образом словарь в Python упрощает поиск в структурах с большим объемом данных.

Ключами могут выступать следующие типы данных:

  • строки,

  • числа (целые и дробные),

  • кортежи.

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

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

В этом руководстве используется Python версии 3.10.12.

С помощью фигурных скобок {}

Наиболее простой и наглядный способ создать словарь — использовать фигурные скобки.

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

empty_dictionary = {}

А вот так создается словарь с ключами и значениями внутри:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

Имена в кавычках — это ключи, а цифры — их значения.

Показанную ранее таблицу можно выразить в виде словаря следующим образом:

team_phones = {
	"Виктор": "+7 905 600 50 40",
	"Юлия": "+7 960 540 43 32",
	"Александр": "+7 960 830 72 61"
}

В этом случае значения имеют строковый тип, а не числовой.

Кстати, вместо двойных кавычек можно использовать одинарные:

team_phones = {
	'Виктор': '+7 905 600 50 40',
	'Юлия': '+7 960 540 43 32',
	'Александр': '+7 960 830 72 61'
}

С помощью функции dict()

Как и со многими другими типами переменных, словарь можно создать с помощью соответствующей ему функции.

Например, так создается пустой словарь:

just_dictionary = dict()

А так можно создать словарь с ключами и значениями:

keys_and_values = [("Александр", 23), ("Виктория",43), ("Евгений", 26), ("Петр", 52), ("Денис", 32)]

team_ages = dict(keys_and_values)

В этом случае сперва создается список с так называемыми кортежами — парами «ключ — значение».

Однако, есть и более лаконичный способ создать словарь через функцию:

team_ages = dict(Александр = 23, Виктория = 43, Евгений = 26, Петр = 52, Денис = 32)

Таким образом, каждый аргумент функции превращается в ключ со значением нового словаря.

С помощью функции dict.fromkeys()

Еще один способ создать словарь — преобразовать в него список. Здесь есть несколько нюансов:

  • Элементы списка станут ключами нового словаря

  • Можно задать значение по умолчанию для всех ключей сразу, а не для каждого отдельного

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

team_names = ["Александр", "Виктория", "Евгений", "Петр", "Денис"] # список с ключами

team_ages = dict.fromkeys(team_names)

print(team_ages)

Консольный вывод будет следующий:

{'Александр': None, 'Виктория': None, 'Евгений': None, 'Петр': None, 'Денис': None}

А вот так создается словарь с указанием значения, которое будет общим для всех ключей:

team_names = ["Александр", "Виктория", "Евгений", "Петр", "Денис"]

team_ages = dict.fromkeys(team_names, 0) # указываем значение по умолчанию вторым аргументом

print(team_ages)

В этом случае консольный вывод будет таким:

{'Александр': 0, 'Виктория': 0, 'Евгений': 0, 'Петр': 0, 'Денис': 0}

❯ Генерация словаря

Более нестандартный способ создания словаря — его генерация из других данных с помощью так называемого генератора словаря, представляющего собой компактный цикл for, внутри которого прописываются правила генерации словаря.

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

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

team_names = ["Александр", "Виктория", "Евгений", "Петр", "Денис"]

team_ages = {name : 0 for name in team_names} # генератор словаря со числом в качестве значения по умолчанию

print(team_ages)

Консольный вывод будет аналогичным предыдущему:

{'Александр': 0, 'Виктория': 0, 'Евгений': 0, 'Петр': 0, 'Денис': 0}

Однако основное преимущество генератора словаря — возможность задавать индивидуальное значение для каждого ключа.

Для этого нужно подготовить два списка и несколько усложнить базовую запись генератора:

team_names = ["Александр", "Виктория", "Евгений", "Петр", "Денис"]
team_numbers = [23, 43, 26, 52, 32]

team_ages = {name : age for name, age in zip(team_names, team_numbers)} # используем вспомогательную функцию zip() для итерирования сразу двух листов

print(team_ages)

Функция zip() преобразует два списка в список кортежей, по которому выполняется итерация в цикле генератора.

В этом случае вывод в терминале консоли будет следующим:

{'Александр': 23, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

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

team_data = ["Александр", 23, "Виктория", 43, "Евгений", 26, "Петр", 52, "Денис", 32] # ключи и значения последовательно записаны внутри одного списка

team_ages = {team_data[i] : team_data[i+1] for i in range(0, len(team_data), 2)} # продолжительность цикла равна длине списка, а шаг итерирования равен двум

print(team_ages)

В этом примере используется функция range(), которая устанавливает длину и шаг итерирования в цикле.

Консольный вывод неотличим от предыдущих:

{'Александр': 23, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

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

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

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

team_ages["Екатерина"] = 28 # записываем значение по новому ключу

print(team_ages)

Консольный вывод будет таким:

{'Александр': 24, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32, 'Екатерина': 28}

❯ Изменение элементов

Изменение элемента синтаксически не отличается от его добавления, за тем исключением, что элемент уже существует внутри словаря:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

team_ages["Виктория"] = 44 # обновляем уже существующее значение

print(team_ages)

Вывод в консольном терминале окажется таким:

{'Александр': 24, 'Виктория': 44, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

❯ Получение элементов

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

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

print(team_ages["Евгений"])

Вывод в терминале консоли будет таким:

26

Либо более наглядный пример с ранее показанной таблицей:

team_phones = {
	"Виктор": "+7 905 600 50 40",
	"Юлия": "+7 960 540 43 32",
	"Александр": "+7 960 830 72 61"
}

print(team_phones["Юлия"])

В этом случае консольный вывод будет следующим:

 +7 960 540 43 32

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

Удалить элемент из словаря можно с помощью специального ключевого слова:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

del team_ages["Виктория"]

print(team_ages)

Соответственно, консольный вывод не будет содержать удаленный элемент:

{'Александр': 23, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

❯ Управление элементами

У словаря есть набор специальных методов для управления элементами внутри — ключами и значениями. Многие из этих методов дублируют ранее показанные функции добавления, изменения и удаления.

Функция dict.update()

Этот метод добавляет в словарь новые элементы путем передачи другого словаря в качестве аргумента:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

team_ages.update({
	"Иван": 32,
	"Екатерина": 28
})

print(team_ages)

В консоли появится следующий вывод:

{'Александр': 24, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32, 'Иван': 32, 'Екатерина': 28}

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

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}
team_add = {"Иван": 32, "Екатерина": 28}

team_ages.update(team_add)

print(team_ages)

Разумеется, вывод аналогичный:

{'Александр': 24, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32, 'Иван': 32, 'Екатерина': 28}

Функция dict.get()

Получить доступ к значению можно не только с помощью квадратных скобок, но и через соответствующую функцию:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

print(team_ages.get("Виктория"))
print(team_ages["Виктория"])

Оба консольных вывода будут одинаковые:

43
43

А вот что будет, если в качестве аргумента передать несуществующий ключ:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

print(team_ages.get("Анастасия"))

Консольный вывод будет уже таким:

None

Однако главная особенность get() в отличие от квадратных скобок — возможность задать значение для несуществующего ключа в качестве второго аргумента:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

print(team_ages.get("Анастасия", "Несуществующий сотрудник"))

В этом случае консольный вывод станет таким:

Несуществующий сотрудник

При использовании квадратных скобок пришлось бы использовать блок обработки ошибок try / except в тех случаях, когда нет уверенности в существовании ключа.

Функция dict.pop()

В словарях есть отдельная функция для удаления элемента по ключу:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

team_ages.pop("Александр")

print(team_ages)

Вывод в терминале консоли будет следующим:

  {'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

Функция dict.popitem()

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

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}
team_add = {"Иван": 32, "Екатерина": 28}

team_ages.update({"Иван": 32})

print(team_ages)

team_ages.popitem()

print(team_ages)

В терминале консоли появится как содержимое словаря с добавленным элементом, так и содержимое после его удаления:

{'Александр': 23, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32, 'Иван': 32}
{'Александр': 23, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

Функция dict.clear()

Словарь можно полностью очистить с помощью соответствующего метода:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

team_ages.clear()

print(team_ages)

В консольном выводе окажется пустой словарь:

{}

Функция dict.copy()

Словарь можно полностью скопировать:

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

team_ages_copy = team_ages.copy()

print(team_ages)
print(team_ages_copy)

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

{'Александр': 23, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32}
{'Александр': 23, 'Виктория': 43, 'Евгений': 26, 'Петр': 52, 'Денис': 32}

Функция dict.setdefault()

Механики добавления или извлечения ключа иногда недостаточно. Зачастую нужно более сложное поведение.

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

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

team_ages = {"Александр": 23, "Виктория": 43, "Евгений": 26, "Петр": 52, "Денис": 32}

print(team_ages.setdefault("Александр")) # такой ключ уже есть

print(team_ages.setdefault("Иван")) # такого ключа еще нет, поэтому он будет создан со значением None

print(team_ages.setdefault("Екатерина", 29)) # такого ключа еще нет, поэтому он будет создан со значением 29

В терминале консоли появится вывод по всем запрашиваемым именам вне зависимости от того, существовали ли они в момент выполнения функции или нет:

23
None
29

❯ Преобразование словаря

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

Для извлечения данных из словаря в языке программирования Python есть несколько функций:

  • dict.keys() — возвращает объект с ключами

  • dict.values() — возвращает объект со значениями

  • dict.items() — возвращает объект с кортежами «ключ — значение»

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

team_phones = {
	"Виктор": "+7 905 600 50 40",
	"Юлия": "+7 960 540 43 32",
	"Александр": "+7 960 830 72 61"
}

# все возвращаемые объекты конвертируются в списки через функцию list()

team_names = list(team_phones.keys()) # список с ключами словаря
team_numbers = list(team_phones.values()) # список со значениями словаря
team_all = list(team_phones.items()) # список с парами «ключ-значение» словаря

print(team_names)
print(team_numbers)
print(team_all)

Вывод в консольном терминале будет таким:

['Виктор', 'Юлия', 'Александр']
['+7 905 600 50 40', '+7 960 540 43 32', '+7 960 830 72 61']
[('Виктор', '+7 905 600 50 40'), ('Юлия', '+7 960 540 43 32'), ('Александр', '+7 960 830 72 61')]

В примере выше выполняется явная конвертация возвращаемых словарем объектов в списки.

Однако, это можно и не делать:

team_phones = {
	"Виктор": "+7 905 600 50 40",
	"Юлия": "+7 960 540 43 32",
	"Александр": "+7 960 830 72 61"
}

print(team_phones.keys())
print(team_phones.values())
print(team_phones.items())

В консольном терминале появится следующий вывод:

dict_keys(['Виктор', 'Юлия', 'Александр'])
dict_values(['+7 905 600 50 40', '+7 960 540 43 32', '+7 960 830 72 61'])
dict_items([('Виктор', '+7 905 600 50 40'), ('Юлия', '+7 960 540 43 32'), ('Александр', '+7 960 830 72 61')])

❯ Заключение

Словарь в языке Python — неупорядоченная структура данных вида «ключ — значение», с которой можно можно делать следующие операции:

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

  • Генерация словаря из других данных

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

  • Изменение элементов

  • Доступ к элементам

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

  • Управление элементами

  • Преобразование словаря

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


Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud  в нашем Telegram-канале 

Перейти ↩

? Читайте также:

Комментарии (11)


  1. d_ilyich
    30.10.2024 09:10

    Ключами могут выступать следующие типы данных: строки, числа (целые и дробные), кортежи.

    А ещё, например, frozenset

    P.S. Насколько понимаю, ключом может быть любой неизменяемый тип.


    1. fireSparrow
      30.10.2024 09:10

      Если я правильно помню, чтобы объект мог быть ключом, достаточно, чтобы для него было определено хэшерование и сравнение на эквивалентность.

      Причём, для корректной работы подразумевается, что и первое, и второе должны давать одинаковый результат на протяжении всего срока жизни объекта.

      То есть, объект вполне может быть ключом словаря, и при этом иметь внутри себя какие-то изменяемые поля - при условии, что эти поля не влияют на подсчёт хэша и проверку на эквивалентность.


  1. d_ilyich
    30.10.2024 09:10

    Словарь в языке Python — неупорядоченная структура данных

    Это смотря что понимать под упорядоченностью

    Dictionaries preserve insertion order. Note that updating a key does not affect the order. Keys added after deletion are inserted at the end.
    Changed in version 3.7: Dictionary order is guaranteed to be insertion order.

    source

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

    d = {1: "1", 2: "2"}
    s = {"1", "2"}
    print(d, s, sep='\n')
    
    d[3] = "3"
    s.add("0")
    print(d, s, sep='\n')
    


    1. fireSparrow
      30.10.2024 09:10

      Но это особенность конкретной реализации. В целом спецификация языка не гарантирует какого-либо порядка.


      1. d_ilyich
        30.10.2024 09:10

        Ссылка ведёт на официальную документацию, где сказано: "Changed in version 3.7: Dictionary order is guaranteed to be insertion order." Насколько я понимаю, до версии 3.7 порядок не гарантировался, а вот начиная с 3.7 уже гарантируется.


  1. glebasterBajo
    30.10.2024 09:10

    Словарь (dictionary или dict) — это неупорядоченная (в отличие от списка)

    Расходимся. Словари, кажется, с версии 3.6 упорядочены, после того, как их внутреннее устройство поменяли.


  1. fireSparrow
    30.10.2024 09:10

    Про dict.pop() и dict.popitem()

    Упустили важный момент - эти функции не просто удаляют элемент, но и возвращают его значение.

    То есть можно делать так:

    x = data.pop(key)

    # Делаем что-то с x


    1. zzzzzzerg
      30.10.2024 09:10

      В данном случае, если элемент отсутствует вы получите исключение. Но можно делать .pop(Key, None) например.


  1. homm
    30.10.2024 09:10

    Уровень сложности материала: Средний

    Спасибо за 3 минуты потраченного времени на пролистывание этого материала чуть проще чем «Простой»


  1. 0x22
    30.10.2024 09:10

    При копировании через copy(), следует учесть, что если значением элемента словаря будет изменяемый объект, то модификация копии словаря повлечёт изменение значения в оригинале.

    пример:

    import copy
    
    dict_orig = {"a": [1, 2, [8, 8, 8], 3, 4]}
    dict_copy = dict_orig.copy()
    
    print(dict_orig)
    # {'a': [1, 2, [8, 8, 8], 3, 4]}
    print(dict_copy)
    #{'a': [1, 2, [8, 8, 8], 3, 4]}
    
    # в копии словаря добавляем значение в список
    dict_copy["a"][2].append("xxx")
    
    print(dict_orig)
    #{'a': [1, 2, [8, 8, 8, 'xxx'], 3, 4]}
    print(dict_copy)
    #{'a': [1, 2, [8, 8, 8, 'xxx'], 3, 4]}
    
    # изменение повлияло и на оригинал
    
    
    #используя deepcopy:
    
    x_dict_orig = {"a": [1, 2, [8, 8, 8], 3, 4]}
    x_dict_copy = copy.deepcopy(x_dict_orig)
    
    print(x_dict_orig)
    #{'a': [1, 2, [8, 8, 8], 3, 4]}
    print(x_dict_copy)
    #{'a': [1, 2, [8, 8, 8], 3, 4]}
    
    # в копии словаря добавляем значение в список
    x_dict_copy["a"][2].append("xxx")
    
    print(x_dict_orig)
    #{'a': [1, 2, [8, 8, 8], 3, 4]}
    print(x_dict_copy)
    #{'a': [1, 2, [8, 8, 8, 'xxx'], 3, 4]}
    
    # оригинал не изменился
    

    для безопасного копирования лучше использовать функцию deepcopy модуля copy


  1. PaperParrot
    30.10.2024 09:10

    Для этого нужно подготовить два списка и несколько усложнить базовую запись генератора

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

    team_names = ["Александр", "Виктория", "Евгений", "Петр", "Денис"]
    team_numbers = [23, 43, 26, 52, 32]
    # team_ages = {name : age for name, age in zip(team_names,team_numbers)} # используем вспомогательную функцию zip() для итерирования сразу двух листов
    team_ages = dict(zip(team_names, team_numbers))
    print(team_ages)