Введение
Словарь — это пример хранилища значений ключей, также известного как 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}
fishdog
# {'name': 'Clifford', 'hands': 'paws', 'special': 'gills', 'color': 'red'}
В этом примере, дубликаты ключей соответствуют последнему значению (например, «Клиффорд» переопределяет «Немо»).
Python 3.3+
from collections import ChainMap
dict(ChainMap(fish, dog))
# {'name': 'Nemo', 'hands': 'fins', 'color': 'red', 'special': 'gills'}
Здесь первостепенное значение отдаётся кокретному ключу, а не последнему («Клиффорд» выбрасывается в пользу «Немо»).
Python 2.x, 3.x
from itertools import chain
dict(chain(fish.items(), dog.items()))
# {'name': 'Clifford', 'hands': 'paws', 'special': 'gills', 'color': 'red'}
Здесь используется последнее значение, как и в методе слияния [**] («Клиффорд» переопределяет «Немо»).
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)]
Это дает нам следующий список, хранящийся в переменной combinations
:
print(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])
# a 1
# b 2
# c 3
Работает таким же образом в генераторах:
print([key for key in d])
# ['a', 'b', 'c']
Метод items()
можно использовать для одновременного зацикливания ключа и значения:
for key, value in d.items():
print(key, value)
# a 1
# b 2
# c 3
Метод values()
можно использовать для перебора только значений:
for key, value in d.values():
print(key, value)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: cannot unpack non-iterable int object
for value in d.values():
print(value)
# 1
# 2
# 3
Создание словаря
Правила создания словаря:
- каждый ключ должен быть уникальным (иначе он будет переопределен);
- каждый ключ должен быть хэшируемым (для хеширования применяется функция 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;
- для ключей нет определённого порядка.