Перейти к основному содержимому

Словари (dict) в Python

Как выглядит словарь python

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

dictionary = {'персона': 'человек',
'марафон': 'гонка бегунов длиной около 26 миль',
'противостоять': 'оставаться сильным, несмотря на давление',
'бежать': 'двигаться со скоростью'}

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

Вот ещё один пример словаря, где ключами являются числа, а значениями — строки:

gender_dict = {0: 'муж',
1: 'жен'}
story_count = {'сто': 100,
'девяносто': 90,
'двенадцать': 12,
'пять': 5}

Особенности словаря

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

dictionary = {(1, 2.0): 'кортежи могут быть ключами',
1: 'целые числа могут быть ключами',
'бежать': 'строки тоже',
['носок', 1, 2.0]: 'а списки не могут'}

Прим. перев. На самом деле проблема не с изменяемыми, а с нехэшируемыми типами данных, но обычно это одно и то же.

Еще момент.
Числовые ключи в словарях подчиняются правилам сравнения чисел. Таким образом, int(1) и float(1.0) считаются одинаковым ключом, к стати True будет им же. Однако из-за того, что значения типа float сохраняются приближенно, не рекомендуется использовать их в качестве ключей.

my_dict = {True: 'yes', 1: 'no', 1.0: 'maybe'}
# {True: 'maybe'}

Работа со словарями

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

C помощью литерала:

d = {}
# {}

d = {'dict_key': 1, 'dictionary': 2}
# {'dict_key': 1, 'dictionary': 2}

C помощью функции dict

d = dict(short='dict', long='dictionary')
# {'short': 'dict', 'long': 'dictionary'}

d = dict([(1, 1), (2, 4)])
# {1: 1, 2: 4}

d_str = dict(("ab", "bc"))
# {"a": "b", "b": "c"}

С помощью метода fromkeys

d = dict.fromkeys(['a', 'b'])
# {'a': None, 'b': None}

d = dict.fromkeys(['a', 'b'], 100)
# {'a': 100, 'b': 100}

С помощью упаковщика zip

key_list = ['marvel_hero', 'dc_hero']
value_list = ['Spiderman', 'Flash']
superhero_dict = dict(zip(key_list, value_list))

print((superhero_dict))
# {'marvel_hero': 'Spiderman', 'dc_hero': 'Flash'}

С помощью генераторов словарей

Генераторы словарей. Они имеют похожий на генераторы списков синтаксис, но возвращают словарь:

d = {a: a ** 2 for a in range(7)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36}

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

Но принцип довольно простой

# Явно
{ key:value for item in list if conditional }

# функцией dict
dict((key, value) for item in list if condition)

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

list_of_keys = ['q', 'w', 'e', 'r', 't']
generated_dict = {k: 0 for k in list_of_keys}

print(generated_dict)
# {'q': 0, 'w': 0, 'e': 0, 'r': 0, 't': 0}

Получение данных из словаря

Для получения значения конкретного ключа используются квадратные скобки []. Предположим, что в нашем словаре есть пара 'марафон': 26.

dictionary = {'марафон': 26}

# берём значение с ключом "марафон"
dictionary['марафон']
# 26

Опять же, вы получите ошибку, если попытаетесь получить значение по несуществующему ключу.
Для избежания подобных ошибок существует метод get.

Добавление и обновление ключей

Добавление новых пар в словарь происходит достаточно просто:

# Добавляем ключ "туфля" со значением "род обуви, закрывающей ногу не выше щиколотки"
dictionary['туфля'] = 'род обуви, закрывающей ногу не выше щиколотки'

Обновление существующих значений происходит абсолютно также:

# Обновляем ключ "туфля" и присваиваем ему значение "хорошая туфля"
dictionary['туфля'] = 'хорошая туфля'

Удаление ключей

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

# Удаляем значение с ключом "противостоять" из словаря
del dictionary['противостоять']

Методы словарей

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

dict.clear()

Метод clear позволяет очистить словарь:

london = {'name': 'London1', 'location': 'London Str'}

london.clear()
# {}

dict.copy()

Метод copy позволяет создать полную копию словаря.

Если указать, что один словарь равен другому:

london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'}
london2 = london
id(london)
# 25489072

id(london2)
# 25489072

london['vendor'] = 'Juniper'

london2['vendor']
# 'Juniper'

В этом случае london2 это еще одно имя, которое ссылается на словарь. И при изменениях словаря london меняется и словарь london2, так как это ссылки на один и тот же объект.

Поэтому, если нужно сделать копию словаря, надо использовать метод copy():

london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'}
london2 = london.copy()

id(london)
# 25524512

id(london2)
# 25563296

london['vendor'] = 'Juniper'

london2['vendor']
# 'Cisco'

dict.get()

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

# Допустим, у нас есть словарь story_count
story_count = {'сто': 100,
'девяносто': 90,
'двенадцать': 12,
'пять': 5}

Метод get() возвращает значение по указанному ключу. Если указанного ключа не существует, метод вернёт None.

# Ключ "двенадцать" существует и метод get в данном случае вернёт 12
story_count.get('двенадцать')
# 12

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

story_count.get('два')
# None

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

# Метод вернёт 0 в случае, если данного ключа не существует
story_count.get('два', 0)

dict.update()

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

# Начальный словарь
dictionary = {'персона': 'человек',
'марафон': 'гонка бегунов длиной около 26 миль',
'противостоять': 'оставаться сильным, несмотря на давление',
'бежать': 'двигаться со скоростью'}

# Добавляем две пары в словарь dictionary, используя метод update
dictionary.update({'бежал': 'бежать в прошедшем времени',
'туфли': 'туфля во множественном числе'})

print(dictionary)

# {'марафон': 'гонка бегунов длиной около 26 миль',
# 'персона': 'человек',
# 'бежал': 'бежать в прошедшем времени',
# 'бежать': 'двигаться со скоростью',
# 'туфля': 'род обуви, закрывающей ногу не выше щиколотки',
# 'туфли': 'туфля во множественном числе'}

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

dict.pop()

Метод pop() удаляет ключ и возвращает соответствующее ему значение.

story_count = {'сто': 100,
'девяносто': 90,
'двенадцать': 12,
'пять': 5}

story_count.pop('девяносто')
# >>> 90
print(story_count)
# >>> {'двенадцать': 12, 'сто': 100, 'пять': 5}

dict.setdefault()

Метод setdefault ищет ключ, и если его нет, вместо ошибки создает ключ со значением None.

london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'}

ios = london.setdefault('ios')

print(ios)
# None

print(london)
# {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'ios': None}

Если ключ есть, setdefault возвращает значение, которое ему соответствует:

london.setdefault('name')
# 'London1'

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

    In [26]: model = london.setdefault('model', 'Cisco3580')

In [27]: print(model)
Cisco3580

In [28]: london
Out[28]:
{'name': 'London1',
'location': 'London Str',
'vendor': 'Cisco',
'ios': None,
'model': 'Cisco3580'}

Метод setdefault заменяет такую конструкцию:

if key in london:
value = london[key]
else:
london[key] = 'somevalue'
value = london[key]

dict.keys()

Метод keys() возвращает коллекцию ключей в словаре.

story_count = {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5}
print(story_count.keys())

# dict_keys(['сто', 'девяносто', 'двенадцать', 'пять'])

dict.values()

Метод values() возвращает коллекцию значений в словаре.

story_count = {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5}
print(story_count.values())

# dict_values([100, 90, 12, 5])

dict.items()

Метод items() возвращает пары «ключ — значение».

story_count = {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5}
story_count.items()

# dict_items([('сто', 100), ('девяносто', 90), ('двенадцать', 12), ('пять', 5)])

Примеры

Итерация через словарь

Вы можете провести итерацию по каждому ключу в словаре.

story_count = {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5}
for key in story_count:
print(key)

# сто
# девяносто
# двенадцать
# пять

Очевидно, вместо story_count можно использовать story_count.keys().

В примере кода ниже ниже цикл for использует метод items() для получения пары «ключ — значение» на каждую итерацию.

for key, value in story_count.items():
print(key, value)

# сто 100
# девяносто 90
# двенадцать 12
# пять

Сортировка словаря

Сотритовка может производиться разными способами. Пример сортировки с помощью функции sorted.

people = {3: "Jim", 2: "Jack", 4: "Jane", 1: "Jill"}

# Sort by key
dict(sorted(people.items()))
# {1: 'Jill', 2: 'Jack', 3: 'Jim', 4: 'Jane'}

# Sort by value
dict(sorted(people.items(), key=lambda item: item[1]))
# {2: 'Jack', 4: 'Jane', 1: 'Jill', 3: 'Jim'}

Обрезка словаря

Если из большого словаря необходимо получить, только его часть. (например 10 самых частых элементов). Можно использовать метод islice
из itertools

from itertools import islice

story_count = {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5, 'семь': 7}
nd = dict(islice(story_count.items(), 0, 3))
# {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5, 'семь': 7}

islice

dict to list

Для конвертации dict в list достаточно проитерировать словарь попарно с помощью метода items(), и, на каждой итерации, добавлять пару ключ:значение к заранее созданному списку. На выходе получим список списков, где каждый подсписок есть пара из исходного словаря.

medicine_chest = dict(top_part='potion', bot_part='bandage')
medicine_list = []
for key, con in medicine_chest.items():
temp = [key, con]
medicine_list.append(temp)

# [['top_part', 'potion'], ['bot_part', 'bandage']]

Тот же результат в одну строчку

my_dict = {'сто': 100, 'девяносто': 90, 'двенадцать': 12, 'пять': 5}
nl = [[k, v] for k, v in my_dict.items()]

# [['сто', 100], ['девяносто', 90], ['двенадцать', 12], ['пять', 5]]