Словарь (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)
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.Если запустить несколько раз нижеприведённый код (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')
fireSparrow
30.10.2024 09:10Но это особенность конкретной реализации. В целом спецификация языка не гарантирует какого-либо порядка.
d_ilyich
30.10.2024 09:10Ссылка ведёт на официальную документацию, где сказано: "Changed in version 3.7: Dictionary order is guaranteed to be insertion order." Насколько я понимаю, до версии 3.7 порядок не гарантировался, а вот начиная с 3.7 уже гарантируется.
glebasterBajo
30.10.2024 09:10Словарь (dictionary или dict) — это неупорядоченная (в отличие от списка)
Расходимся. Словари, кажется, с версии 3.6 упорядочены, после того, как их внутреннее устройство поменяли.
fireSparrow
30.10.2024 09:10Про dict.pop() и dict.popitem()
Упустили важный момент - эти функции не просто удаляют элемент, но и возвращают его значение.
То есть можно делать так:
x = data.pop(key)
# Делаем что-то с x
zzzzzzerg
30.10.2024 09:10В данном случае, если элемент отсутствует вы получите исключение. Но можно делать .pop(Key, None) например.
homm
30.10.2024 09:10Уровень сложности материала: Средний
Спасибо за 3 минуты потраченного времени на пролистывание этого материала чуть проще чем «Простой»
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
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)
d_ilyich
А ещё, например,
frozenset
P.S. Насколько понимаю, ключом может быть любой неизменяемый тип.
fireSparrow
Если я правильно помню, чтобы объект мог быть ключом, достаточно, чтобы для него было определено хэшерование и сравнение на эквивалентность.
Причём, для корректной работы подразумевается, что и первое, и второе должны давать одинаковый результат на протяжении всего срока жизни объекта.
То есть, объект вполне может быть ключом словаря, и при этом иметь внутри себя какие-то изменяемые поля - при условии, что эти поля не влияют на подсчёт хэша и проверку на эквивалентность.