Словари¶
Автор(ы)
Что такое dict¶
dict (от английского «dictionary», словарь) – еще один тип данных в Python. Словари хранят пары ключ: значение. То есть в списках можно достать элемент, если указать его позицию в виде целого числа, а в словарях – тот самый ключ. dict – неупорядоченный тип данных, поэтому достать элемент по номеру не получится, но отображение содержимого будет в порядке добавления элементов. Уникальность ключей должна поддерживаться, чтобы всегда можно было быстро найти одно единственно верное значение.
В некоторых языках программирования можно встретить ассоциативные массивы – полную аналогию dict. Также вспомним базы данных, широко использующиеся во всём мире для хранения информации: в таблице можно установить первичный ключ, который уникально идентифицирует запись, как и ключ соответствует значению в словаре. Самый простой пример ключа - порядковый номер объекта!
Создание словаря¶
Использовать словарь стоит, когда нужно сохранять объекты с какими-то ключами и обращаться к объектам по известным ключам. Один из способов определения словаря: указание пар ключ: значение через^запятую внутри фигурных скобок {}. Напоминает set, правда? {} позволяет создать пустой словарь, но не пустое множество.
Например, решили упростить себе жизнь и больше не запоминать дни рождения коллег. Вместо этого, лучше хранить их в одном месте:
В примере dates имеет две пары значений. В первой паре строка "Кунг Фьюри" является ключом, а "1968-09-09" – его значением.
Получение значения по ключу¶
Чтобы получить значение по ключу, необходимо обратиться к переменной, содержащей словарь, и указать ключ в квадратных скобках []:
Если указать неверный ключ в [], Python будет ругаться: выбросит ошибку KeyError и перестанет выполнять код. Чуть ниже посмотрим, как можно избежать таких ситуаций.
Изменение и добавление значений¶
Синтаксис изменения значения по ключу и добавления нового ключа со значением одинаковый: в [] нужно указать ключ, поставить = и указать значение, которое теперь будет соответствовать ключу.
Если ключ уже был в словаре, значение по нему изменится на новое, а старое будет удалено. Указание нового ключа со значением добавляет пару в словарь.
Основные методы словаря¶
Проверка вхождения и get()¶
Помните, ранее говорили, что обращение к несуществующему ключу приводит к ошибке? Пришло время посмотреть пару способов борьбы!
Можно проверить, есть ли интересующий ключ среди множества ключей словаря. Это делается при помощи бинарного оператора in. Слева должен быть указан ключ, справа – переменная со словарем:
В коде проверку можно использовать в условной конструкции if, чтобы принимать решение в зависимости от наличия ключа:
Теперь о методе get(): при помощи его тоже можно получать значения из словаря по ключу. KeyError никогда не появится: если ключа нет, по умолчанию возвращается None:
Вторым аргументом метода get() можно указать значение, которое должно возвращаться вместо None, когда ключ не был найден:
Что такое "длина словаря"?¶
Функция len() для словаря будет возвращать количество пар ключ: значение (их столько же, сколько ключей), которое в нём содержится:
Удаление из словаря¶
Есть несколько способов очистки в словаре: можно убирать по ключу, а можно сразу удалить все!
-
при помощи инструкции
del(от английского «delete») можно удалить паруключ:значение(удаление ключа эквивалентно удалению парыключ:значение, так как теряем возможность найти то самоезначение), в общем виде:Предположим, коллега из самого первого примера уволился и больше нет смысла хранить его день рождения:
-
pop()- метод, который достает значение, хранящееся по переданному ключу, и сразу удаляет ключ из словаря:Для метода
pop()есть возможность указать значение, которое будет возвращено при обращении к несуществующему ключу. Почти какget(), но всё-таки, без указания этого значения,pop()выбрасываетKeyError. -
popitem()имеет схожее название, но не путайте с предыдущим методом: этот на вход не принимаетключ, а возвращает паруключ:значение, которая была добавлена последней (такое поведение гарантируется с Python 3.7). -
clear()позволяет удалить сразу все ключи словаря, то есть полностью его очистить:
Важно
Обратите внимание на то, как работают методы pop(), popitem() и clear(): как только вызываются, словарь меняет свой состав (изменения происходят in place, то изменить по месту без копирования).
Обновление и добавление ключей¶
Лицезрели, что значения в словарь можно добавлять или менять, обращаясь по ключу. Python предоставляет возможность не писать кучу присваиваний, а использовать лаконичный метод update(), который на вход может принимать либо другой словарь, либо пары ключ: значение в какой-то последовательности (например, кортежи по два значения в списке: первое – ключ, второе – значение)
А что, если в update() передать пары, ключ которых уже был в словаре? Значения по дублирующимся ключам будут перезаписаны на новые:
Доступ к ключам и значениям¶
В Python можно без проблем извлекать отдельно по ключам или значениям, а также итерироваться по элементам словарей в цикле for. Осталось разобраться, как это работает.
Ключи¶
По умолчанию, в конструкциях вида
переменные цикла (тут – key) будут принимать значения из множества ключей словаря. Аналогично можно использовать метод keys() (позволяет достать все ключи), который явно говорит, что цикл идет по ключам, например:
player = 'Fred Weasley': quidditch_team[player] = '3rd year'
player = 'George Weasley': quidditch_team[player] = '3rd year'
player = 'Harry Potter': quidditch_team[player] = '2nd year'
Значения¶
При помощи метода values() можно получить все значения, хранящиеся по всем ключам словаря:
Между тем
Напрямую по значению получить ключ нельзя.
Всё и сразу¶
Существует метод items(), который достает пары ключ: значение в виде последовательности кортежей. Его же часто удобно использовать в циклах, дабы не тащить длинную запись в виде названия словаря и квадратных скобок с ключом при обращении к значению:
Player Fred Weasley is in 3rd year
Player George Weasley is in 3rd year
Player Harry Potter is in 2nd year
Сортировка¶
Функция sorted() доступна и для словарей. По умолчанию ключи словаря поддерживают порядок, в котором были добавлены, но можно отсортировать их в нужном направлении (в зависимости от типа):
Не забудьте
Когда в функции передаётся просто название переменной со словарем, работа идет только над множеством ключей.
Можно ли отсортировать словарь по значениям?
Да, можно попробовать самостоятельно разобраться с аргументами функции sorted().
Что можно хранить¶
Теперь добавим немного технических подробностей: возможно, уже заметили самостоятельно, что dict может принимать в качестве ключа не всякое значение. На самом деле только хешируемые объекты (можно вызвать функцию hash() и получить значение) могут быть ключами словаря, на значения это ограничение не распространяется. В dict и set значение хеша от объекта используется для поиска внутри структуры.
Ключом словаря нельзя сделать объект изменяемого типа, например, list, set или сам dict, так как значение их хеша может измениться со временем. Неизменяемый кортеж может быть ключом только если не содержит внутри изменяемые объекты.
Изменяемость и неизменяемость¶
В англоязычной литературе изменяемые типы называют mutable, а неизменяемые – immutable, почитать документацию.
В Python всё есть объект. Когда пользователь присваивает значение переменной, она начинает ассоциироваться с ячейкой памяти, где лежит это значение. Переменная знает адрес, откуда можно получить значение. id() и hex() показывают адрес в памяти компьютера. id() - адрес в десятичном виде, а hex() поможет перевести в шестнадцатеричный.
По адресу лежит так называемое внутреннее состояние переменной:
- неизменяемые типы не позволяют менять внутреннее состояние, значение переменной может поменяться только вместе с адресом
- изменяемые типы позволяют менять внутреннее состояние переменной при сохранении адреса (возвращаемое
id()значение не меняется, но значение переменной каким-то образом преобразовывается). Изменение по ссылке называется изменением in place.
Неизменяемые типы¶
Из стандартных неизменяемыми являются:
intfloatboolstrtuple
Давайте сразу рассмотрим пример:
flowchart LR
subgraph 100
0x10c678d50
end
counter --> 100 А теперь поменяем значение counter:
Кажется, что раз значение переменной counter поменялось, то и содержимое по предыдущему адресу изменилось? Нет, на самом деле counter теперь указывает в другое место:
flowchart LR
subgraph 100
0x10c678d50
end
subgraph 200
0x10c6799d0
end
counter --> 200 Из интересного: Python заранее создает объекты для чисел от -5 до 256, поэтому для переменных со значением из этого диапазона берутся заранее готовые ссылки.
Изменяемые типы¶
Стандартные изменяемые типы это:
listsetdict
У списков есть метод append(), позволяющий добавить в него значение:
flowchart LR
subgraph list ["[1, 2, 3]"]
0x10df8d1c0
end
ratings --> list После добавления ещё одного, адрес ratings не изменился.
flowchart LR
subgraph list ["[1, 2, 3, 4]"]
0x10df8d1c0
end
ratings --> list Что узнали из лекции¶
- новый тип данных – словарь! Позволяет хранить соответствие
ключ:значение; -
несколько способов создания
dict, примеры: -
методы для изменения состояния или получения доступа к элементам:
-
требование к ключу: возможность хеширования, свойство ключа внутри словаря: уникальность;
- разобрали, что есть изменяемые (
dict,set,list) и неизменяемые (int,float,bool,tuple,str) стандартные типы данных.