Отображениями называются типы данных, поддерживающие оператор проверки
на вхождение (in
), функцию len()
и возможность обхода элементов в
цикле. Отображения – это коллекции пар элементов «ключ-значение»,
которые предоставляют методы доступа к элементам и их ключам и
значениям. При выполнении итераций порядок следования элементов
отображений может быть произвольным. В языке Python имеется два типа
отображений: встроенный тип dict
и тип collections.defaultdict
,
определяемый в стандартной библиотеке. Мы будем использовать термин
словарь для ссылки на любой из этих типов, когда различия между ними
не будут иметь никакого значения.
В качестве ключей словарей могут использоваться только хешируемые
объекты, поэтому в качестве ключей словаря такие неизменяемые типы,
как float
, frozenset
, int
, str
и tuple
, использовать
допускается, а изменяемые типы, такие как dict
, list
и set
, –
нет. С другой стороны, каждому ключу соответствует некоторое значение,
которое может быть ссылкой на объект любого типа, включая числа,
строки, списки, множества, словари, функции и т. д.
Словари могут сравниваться с помощью стандартных операторов сравнения
(<
, <=
, ==
, !=
, >=
, >
), при этом сравнивание производится
поэлементно (и рекурсивно, при наличии вложенных элементов, таких как
кортежи или словари в словарях). Пожалуй, единственными операторами
сравнения, применение которых к словарям имеет смысл, являются
операторы ==
и !=
.
Тип dict
– это неупорядоченная коллекция из нуля или более пар
«ключ-значение», в которых в качестве ключей могут использоваться
ссылки на хешируемые объекты, а в качестве значений – ссылки на
объекты любого типа. Словари относятся к категории изменяемых типов,
поэтому легко можно добавлять и удалять их элементы, но так как они
являются неупорядоченными коллекциями, к ним не применимо понятие
индекса и не применима операция извлечения среза.
Тип данных dict
может вызываться как функция dict()
– без
аргументов она возвращает пустой словарь; если в качестве аргумента
передается отображение, возвращается словарь, основанный на этом
отображении: например, с аргументом типа dict
возвращается
поверхностная копия словаря. Существует возможность передавать в
качестве аргумента последовательности, если каждый элемент
последовательности в свою очередь является последовательностью из двух
объектов, первый из которых используется в качестве ключа, а второй –
в качестве значения. Как вариант, для создания словарей, в которых
ключи являются допустимыми идентификаторами языка Python, можно
использовать именованные аргументы; тогда имена аргументов будут
играть роль ключей, а значения аргументов – роль значений
ключей. Кроме того, словари могут создаваться с помощью фигурных
скобок – пустые скобки {}
создадут пустой словарь. Непустые фигурные
скобки должны содержать один или более элементов, разделенных
запятыми, каждый из которых состоит из ключа, символа двоеточия и
значения. Еще один способ создания словарей заключается в
использовании генераторов словарей – эта тема будет рассматриваться
ниже, в соответствующем подразделе.
Ниже приводятся несколько способов создания словарей – все они создают один и тот же словарь:
d1 = dict({"id": 1948, "name": "Washer", "size": 3})
d2 = dict(id=1948, name="Washer", size=3)
d3 = dict([("id", 1948), ("name", "Washer"), ("size", 3)])
d4 = dict(zip(("id", "name", "size"), (1948, "Washer", 3)))
d5 = {"id": 1948, "name": "Washer", "size": 3}
Рисунок 5: Словарь – это неупорядоченная коллекция элементов (ключ, значение) с уникальными ключами
На рис. 5 демонстрируется словарь, созданный следующим фрагментом программного кода:
d = {"root": 18, "blue": [75, "R", 2], 21: "venus", -14: None,
"mars": "rover", (4, 11): 18, 0: 45}
Ключи словарей являются уникальными, поэтому если в словарь
добавляется пара «ключ-значение» с ключом, который уже присутствует в
словаре, в результате происходит замена значения существующего ключа
новым значением. Для доступа к отдельным элементам используются
квадратные скобки: например, выражение d["root"]
вернет 18
,
выражение d[21]
вернет строку "venus"
, а выражение d[91]
применительно к словарю, изображенному на
рис. 5, возбудит исключение KeyError
.
Квадратные скобки могут также использоваться для добавления и удаления
элементов словаря. Чтобы добавить новый элемент, используется оператор
=
, например, d["X"] = 59
. Для удаления элементов используется
инструкция del
, например, инструкция del d["mars"]
удалит из
словаря элемент с ключом "mars"
или возбудит исключение KeyError
,
если элемент с указанным ключом отсутствует в словаре. Кроме того,
элементы могут удаляться (и возвращаться вызывающей программе)
методом dict.pop()
.
Словари поддерживают встроенную функцию len()
и для ключей
поддерживают возможность быстрой проверки на вхождение с помощью
операторов in
и not in
. В табл. collections:maps:tbl:1
перечислены все методы словарей.
Так как словари содержат пары «ключ-значение», у нас может возникнуть потребность обойти в цикле элементы словаря (ключ, значение) по значениям или по ключам. Например, ниже приводятся два эквивалентных способа обхода пар «ключ-значение»:
for item in d.items():
print(item[0], item[1])
for key, value in d.items():
print(key, value)
Таблица 3. Методы словарей
Синтаксис | Описание |
d.clear() | Удаляет все элементы из словаря d |
d.copy() | Возвращает поверхностную копию словаря d |
d.fromkeys(s, v) | Возвращает словарь типа dict , ключами которого являются элементы последовательности s значениями либо None либо v , если аргумент v определен |
d.get(k) | Возвращает значение ключа k или None , если ключ k отсутствует в словаре |
d.get(k, v) | Возвращает значение ключа k или v , если ключ k отсутствует в словаре |
d.items() | Возвращает представление всех пар (ключ, значение) в словаре d |
d.keys() | Возвращает представление всех ключей словаря d |
d.pop(k) | Возвращает значение ключа k и удаляет из словаря элемент с ключом k или возбуждает исключение KeyError , если ключ k отсутствует в словаре |
d.pop(k, v) | Возвращает значение ключа k и удаляет из словаря элемент с ключом k или возвращает значение v , если ключ k отсутствует в словаре |
d.popitem() | Возвращает и удаляет произвольную пару (ключ, значение) из словаря d или возбуждает исключение KeyError , если словарь d пуст |
d.setdefault(k, v) | То же что и dict.get() за исключением того, что, если ключ k в словаре отсутствует, в словарь вставляется новый элемент с ключом k и со значением None или v , если аргумент v задан |
d.update(a) | Добавляет в словарь d пары (ключ, значение) из a , которые отсутствуют в словаре d а для каждого ключа который уже присутствует в словаре d выполняется замена соответствующим значением из a ; a может быть словарем итерируемым объектом с парами (ключ значение) или именованными аргументами |
d.values() | Возвращает представление всех значений в словаре d |
Обход значений в словаре выполняется похожим способом:
for value in d.values():
print(value)
Для обхода ключей в словаре можно использовать метод dict.keys()
или просто интерпретировать словарь как итерируемый объект и вы-
полнить итерации по его ключам, как показано в следующих двух
фрагментах:
for key in d:
print(key)
for key in d.keys():
print(key)
Если необходимо изменить значения в словаре, то можно выполнить
обход ключей словаря в цикле и изменить значения, используя оператор
квадратных скобок. Например, ниже показано, как можно было бы
увеличить все значения в словаре d
, если предполагать, что все
значения являются числами:
for key in d:
d[key] += 1
Методы dict.items()
, dict.keys()
и dict.values()
возвращают
представления словарей. Представление словаря – это в действительности
итерируемый объект, доступный только для чтения и хранящий элементы,
ключи или значения словаря в зависимости от того, какое представление
было запрошено.
Генератор словарей – это выражение и цикл с необязательным условием, заключенное в фигурные скобки, очень напоминающее генератор множеств. Подобно генераторам списков и множеств, генераторы словарей поддерживают две формы записи:
{keyexpression: valueexpression for key, value in iterable}
{keyexpression: valueexpression for key, value in iterable if condition}
Ниже показано, как можно использовать генератор словарей для создания словаря, в котором каждый ключ является именем файла в текущем каталоге, а каждое значение – это размер файла в байтах:
file_sizes = {name: os.path.getsize(name) for name in os.listdir(".")}
Функция os.listdir()
из модуля os («operating system» – операционная
система) возвращает список файлов и каталогов в указанном каталоге, но
при этом в список никогда не включаются специальные имена каталогов
«.» или «..». Функция os.path.getsize() возвращает размер заданного
файла в байтах. Чтобы отфильтровать каталоги и другие элементы списка,
не являющиеся файлами, можно добавить дополнительное условие:
file_sizes = {name: os.path.getsize(name) for name in os.listdir(".")
if os.path.isfile(name)}
Функция os.path.isfile()
из модуля os.path
возвращает True
, если
указанный путь соответствует файлу, и False
– в противном случае, то
есть для каталогов, ссылок и тому подобного.
Генераторы словарей могут также использоваться для создания инвер-
тированных словарей. Например, пусть имеется словарь d
, тогда мы
можем создать новый словарь, ключами которого будут значения словаря
d
, а значениями – ключи словаря d
:
inverted_d = {v: k for k, v in d.items()}
Полученный словарь можно инвертировать обратно и получить
первоначальный словарь – при условии, что все значения в
первоначальном словаре были уникальными, однако инверсия будет терпеть
неудачу, с возбуждением исключения TypeError
, если какое-либо
значение окажется не хешируемым.
Словари со значениями по умолчанию – это обычные словари, они поддерживают те же самые методы и операторы, что и обычные словари. Единственное, что отличает такие словари от обычных словарей, – это способ обработки отсутствующих ключей, но во всех остальных отношениях они ничем не отличаются друг от друга.
При обращении к несуществующему («отсутствующему») ключу слова-
ря возбуждается исключение KeyError
. Это очень удобно, так как
нередко для нас бывает желательно знать об отсутствии ключа, который,
согласно нашим предположениям, может присутствовать. Но в некоторых
случаях бывает необходимо, чтобы в словаре присутствовали все ключи,
которые мы используем, даже если это означает, что элемент с заданным
ключом добавляется в словарь в момент первого обращения к нему.
Например, допустим, что имеется словарь d
, который не имеет элемента
с ключом m, тогда выражение x = d[m]
возбудит исключение
KeyError
. Если d
– это словарь со значениями по умолчанию,
созданный соответствующим способом, а элемент с ключом m принадлежит
такому словарю, то при обращении к нему будет возвращено
соответствующее значение, как и в случае с обычным словарем. Но если в
словаре со значениями по умолчанию отсутствует ключ m, то будет создан
новый элемент словаря с ключом m и со значением по умолчанию, и будет
возвращено значение этого, вновь созданного элемента.