Введение

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

Примеры

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

dictionary = {"Hello": 1234, "World": 5678}
print(dictionary["Hello"])

Приведённый выше код выведет 1234.

Строка "Hello" в этом примере называется ключом. Он используется для поиска значения в словаре, помещая ключ в квадратные скобки.

Число 1234 видно после соответствующего двоеточия в словаре. Это значение, на которое ведёт "Hello" в словаре.

Поиск значения, с несуществующим  ключом, вызовет исключение KeyError, остановив выполнение. Если мы хотим получить доступ к значению, без риска получить KeyError, мы можем использовать метод dictionary.get. По умолчанию, если ключ не существует, метод вернет None. Мы можем передать ему второе значение, чтобы вернуть вместо None в случае неудачного поиска.

w = dictionary.get("whatever")

x = dictionary.get("whatever", "nuh-uh")

В этом примере w получит значение None, а x получит значение "nuh-uh".

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

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

dict(a=1, b=2, c=3)			# {'a': 1, 'b': 2, 'c': 3}
dict([('d', 4), ('e', 5), ('f', 6)])	# {'d': 4, 'e': 5, 'f': 6}
dict([('a', 1)], b=2, c=3)		# {'a': 1, 'b': 2, 'c': 3}
dict({'a' : 1, 'b' : 2}, c=3)		# {'a': 1, 'b': 2, 'c': 3}

Как избегать исключений KeyError

Распространённая ошибка при использовании словарей — доступ к несуществующему ключу. Это обычно приводит к исключению KeyError:

mydict = {}
mydict['not there']

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'not there'

Один из способов избежать KeyError — использовать метод dict.get, который позволяет вам указать значение по умолчанию, которое будет возвращать в случае отсутствия ключа.

value = mydict.get(key, default_value)

Возвращает mydict[key], если он существует, но в противном случае возвращает default_value. Обратите внимание, что это не добавляет key к mydict. Поэтому, если вы хотите сохранить эту пару ключ-значение, вы должны использовать mydict.setdefault(key, default_value), который хранит пару ключ-значение.

mydict = {}
print(mydict)
# {}
print(mydict.get("foo", "bar"))
# bar
print(mydict)
# {}
print(mydict.setdefault("foo", "bar"))
# bar
print(mydict)
# {'foo': 'bar'}

Другой способ избавиться от ошибки — перехватить исключение

try:  value = mydict[key]except KeyError:  value = default_value

Вы также можете проверить, есть ли ключ словаре:

if key in mydict:  value = mydict[key]else:  value = default_value

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

В качестве другого вариант можно использовать подкласс dict collection.defaultdict, который имеет значение default_factory для создания новых записей в dict при получении new_key.

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

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

Словарь будет таким:

mydict = {    'a': '1',    'b': '2'}

Вы можете получить список ключей, используя метод keys или функцию dict_keys:

print(mydict.keys())
dict_keys(['b', 'a'])

Если вместо этого вы хотите получить список значений, используйте метод values или функцию dict_values:

print(mydict.values())
dict_values(['2', '1'])


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

print(mydict.items())
dict_items([('b', '2'), ('a', '1')])

Примечание. Поскольку словари не отсортированы, keys,  values и items не имеют порядка сортировки. Используйте функции sort, sorted или класс OrderedDict, если вам важен порядок, в котором возвращают эти методы.

Введение в словарь

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

Словари можно создавать разными способами:


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

d = {}               # пустой словарь
d = {"key": "value"} # словарь с начальными значениями

# Распаковка одного или нескольких словарей литералом
d = {**otherdict}                   # создаёт копию otherdict
d = {**otherdict, **yetanotherdict} # создает копию otherdict и butanotherdict

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

d = {k:v for k,v in [('key', 'value',)]}

Через встроенный класс dict()

d = dict()                   # пустой словарь
d = dict(key='value')        #точные именованные аргументы
d = dict([('key', 'value')]) # передаёт в список пар key/value
d = dict(**otherdict)        # делает мелкую копию another dict (возможно только если все ключи являются строками!)

Модификация словаря

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

d['newkey'] = 42

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

d['new_list'] = [1, 2, 3]
d['new_dict'] = {'nested_dict': 1}

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

Словари со значениями по умолчанию

Доступно в стандартной библиотеке как defaultdict

from collections import defaultdict
d = defaultdict(int)
d['key']                         # 0
d['key'] = 5
d['key']                         # 5
d = defaultdict(lambda: 'empty')
d['key']                         # 'empty'
d['key'] = 'full'
d['key']                         # 'full'

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

>>> d = {}
{}
>>> d.setdefault('Another_key', []).append("This worked!")
>>> d
{'Another_key': ['This worked!']}

Если вам нужно добавить много значений, dict.setdefault() будет создавать новый экземпляр начального значения (в этом примере a[]) каждый раз, когда оно вызывается, создавая лишнюю нагрузку.

Как создать упорядоченный словарь

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

Используйте OrderedDict из модуля collections. Он будет возвращать элементы словаря в исходном порядке когда переборка завершится:

from collections import OrderedDict
d = OrderedDict()
d['first'] = 1
d['second'] = 2
d['third'] = 3
d['last'] = 4
# Outputs "first 1", "second 2", "third 3", "last 4"
for key in d:
	print(key, d[key])

Распаковка словарей с помощью оператора **

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

>>>
>>> def parrot(voltage, state, action):
...     print("This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !


Начиная с Python 3.5 вы также можете использовать этот синтаксис для объединения произвольного числа объектов [dict].

>>> fish = {'name': "Nemo", 'hands': "fins", 'special': "gills"}
>>> dog = {'name': "Clifford", 'hands': "paws", 'color': "red"}
>>> fishdog = {**fish, **dog}
>>> fishdog

{'hands': 'paws', 'color': 'red', 'name': 'Clifford', 'special': 'gills'}


Этот пример показывает, что дубликаты ключей соответствуют последнему значению (например, «Клиффорд» переопределяет «Немо»).

Объединений словарей

Рассмотрим разные словари:

fish = {'name': "Nemo", 'hands': "fins", 'special': "gills"}
dog = {'name': "Clifford", 'hands': "paws", 'color': "red"}

Python 3.5+

fishdog = {**fish, **dog} # {'hands': 'paws', 'color': 'red', 'name': 'Clifford', 'special': 'gills'}

В этом примере, дубликаты ключей соответствуют последнему значению (например, «Клиффорд» переопределяет «Немо»).

Python 3.3+

from collections import ChainMapdict(ChainMap(fish, dog)) # {'hands': 'fins', 'color': 'red', 'special': 'gills', 'name': 'Nemo'}

Здесь первостепенное значение отдаётся кокретному ключу, а не последнему («Клиффорд» выбрасывается в пользу «Немо»).

Python 2.x, 3.x

>>> from itertools import chain
>>> dict(chain(fish.items(), dog.items())){'hands': 'paws', 'color': 'red', 'name': 'Clifford', 'special': 'gills'}

Здесь используется последнее значение, как и в методе слияния [**] («Клиффорд» переопределяет «Немо»).

fish.update(dog)
fish # {'color': 'red', 'hands': 'paws', 'name': 'Clifford', 'special': 'gills'}

Замыкающая запятая

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

role = {"By day": "A typical programmer", "By night": "Still a typical programmer", }

PEP 8 требует, чтобы вы оставляли пробел между замыкающей запятой и закрывающей скобкой.

Все комбинации значений словаря

options = {
"x": ["a", "b"],
"y": [10, 20, 30]
}

Дан словарь в примере выше, где есть список, представляющий набор значений для поиска соответствующего ключа. Предположим, вы хотите найти "x"="a" с "y"=10, затем "x"="a" с "y"=10 и т. д.,  пока вы не переберете все возможные комбинации.

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

import itertools

options = {
    "x": ["a", "b"],
    "y": [10, 20, 30]
}

keys = options.keys()
values = (options[key] for key in keys)
combinations = [dict(zip(keys, combination)) for combination in itertools.product(*values)]
print combinations

Это дает нам следующий список, хранящийся в переменной combinations:

[{'x': 'a', 'y': 10},
 {'x': 'b', 'y': 10},
 {'x': 'a', 'y': 20},
 {'x': 'b', 'y': 20},
 {'x': 'a', 'y': 30},
 {'x': 'b', 'y': 30}]

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

Если вы используете словарь в качестве итератора (например, в операторе for), он перемещает ключи в словаре. Например:

d = {'a': 1, 'b': 2, 'c':3}
for key in d:
    print(key, d[key])
# c 3
# b 2
# a 1

Работает таким же образом в генераторах:

print([key for key in d])
# ['c', 'b', 'a']

Метод items() можно использовать для одновременного зацикливания ключа и значения:

for key, value in d.items():
	print(key, value)
# c 3
# b 2
# a 1


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

for key, value in d.values():    print(key, value)    # 3    # 2    # 1

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

Правила создания словаря:

  • каждый ключ должен быть уникальным (иначе он будет переопределен);
  • каждый ключ должен быть хэшируемым (для хеширования применяется функция hash) в противном случае возникнет исключение TypeError;
  • для ключей нет определённого порядка.
#Создание и заполнение значениями
stock = {'eggs': 5, 'milk': 2}

#Создание пустого словаря
dictionary = {}

#И заполнение его позднее
dictionary['eggs'] = 5
dictionary['milk'] = 2

#Значения также могут быть списками
mydict = {'a': [1, 2, 3], 'b': ['one', 'two', 'three']}

#Используй метод list.append() чтобы добавить новый элемент в список значений
mydict['a'].append(4)   # => {'a': [1, 2, 3, 4], 'b': ['one', 'two', 'three']}
mydict['b'].append('four')  # => {'a': [1, 2, 3, 4], 'b': ['one', 'two', 'three', 'four']}

# Мы также можем создать словарь, используя список из двух элементов
iterable = [('eggs', 5), ('milk', 2)]
dictionary = dict(iterables)

# Или используя именованный аргумент:
dictionary = dict(eggs=5, milk=2)

#Другой способ использования dict.fromkeys:
dictionary = dict.fromkeys((milk, eggs))  # => {'milk': None, 'eggs': None}
dictionary = dict.fromkeys((milk, eggs), (2, 5))  # => {'milk': 2, 'eggs': 5}


Примеры словарей

Словари сопоставляют ключи со значениями

car = {}
car["wheels"] = 4
car["color"] = "Red"
car["model"] = "Corvette"

Доступ к значениям словаря осуществляется по их ключам

print "Little " + car["color"] + " " + car["model"] + "!"
# Этот код напечатает "Little Red Corvette!"

Словари также могут быть созданы в стиле JSON:

car = {"wheels": 4, "color": "Red", "model": "Corvette"}

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

for key in car:
	print key + ": " + car[key]

# wheels: 4
# color: Red
# model: Corvette


Синтаксис

mydict = {}
mydict[k] = value
value = mydict[k]
value = mydict.get(k)
value = mydict.get(k, "default_value")

Параметры

Примечания

Что следует помнить при использовании словаря:

– каждый ключ должен быть уникальным (иначе он будет переопределен);

– каждый ключ должен быть хэшируемым (для хеширования применяется функция hash) в противном случае возникнет исключение TypeError;

– для ключей нет определённого порядка.