Словари (dict) и работа с ними. Методы словарей
Сегодня я расскажу о таком типе данных, как словари, о работе со словарями, операциях над ними, методах, о генераторах словарей.
Словари в Python — неупорядоченные коллекции произвольных объектов с доступом по ключу. Их иногда ещё называют ассоциативными массивами или хеш-таблицами.
Чтобы работать со словарём, его нужно создать. Сделать это можно несколькими способами. Во-первых, с помощью литерала:
Во-вторых, с помощью функции dict:
В-третьих, с помощью метода fromkeys:
В-четвертых, с помощью генераторов словарей, которые очень похожи на генераторы списков.
Теперь попробуем добавить записей в словарь и извлечь значения ключей:
: Как видно из примера, присвоение по новому ключу расширяет словарь, присвоение по существующему ключу перезаписывает его, а попытка извлечения несуществующего ключа порождает исключение. Для избежания исключения есть специальный метод (см. ниже), или можно перехватывать исключение.
Что же можно еще делать со словарями? Да то же самое, что и с другими объектами: встроенные функции, ключевые слова (например, циклы for и while), а также специальные методы словарей.
Методы словарей
dict.clear() — очищает словарь.
dict.copy() — возвращает копию словаря.
classmethod dict.fromkeys(seq[, value]) — создает словарь с ключами из seq и значением value (по умолчанию None).
dict.get(key[, default]) — возвращает значение ключа, но если его нет, не бросает исключение, а возвращает default (по умолчанию None).
dict.items() — возвращает пары (ключ, значение).
dict.keys() — возвращает ключи в словаре.
dict.pop(key[, default]) — удаляет ключ и возвращает значение. Если ключа нет, возвращает default (по умолчанию бросает исключение).
dict.popitem() — удаляет и возвращает пару (ключ, значение). Если словарь пуст, бросает исключение KeyError. Помните, что словари неупорядочены.
dict.setdefault(key[, default]) — возвращает значение ключа, но если его нет, не бросает исключение, а создает ключ со значением default (по умолчанию None).
dict.update([other]) — обновляет словарь, добавляя пары (ключ, значение) из other. Существующие ключи перезаписываются. Возвращает None (не новый словарь!).
dict.values() — возвращает значения в словаре.
Для вставки кода на Python в комментарий заключайте его в теги
Что такое словарь в программировании
Словарь (dictionary) в языке Python хранит коллекцию элементов, где каждый элемент имеет уникальный ключ и ассоциированое с ним некоторое значение.
Определение словаря имеет следующий синтаксис:
dictionary =
В фигурных скобках через запятую определяется последовательность элементов, где для каждого элемента сначала указывается ключ и через двоеточие его значение.
users =
В словаре users в качестве ключей используются числа, а в качестве значений - строки. То есть элемент с ключом 1 имеет значение "Tom", элемент с ключом 2 - значение "Bob" и т.д.
emails =
В словаре emails в качестве ключей используются строки - электронные адреса пользователей и в качестве значений тоже строки - имена пользователей.
Но необязательно ключи и строки должны быть однотипными. Они могу представлять разные типы:
objects =
Мы можем также вообще определить пустой словарь без элементов:
objects = <>
objects = dict()
Преобразование списков и кортежей в словарь
Несмотря на то, что словарь и список - непохожие по структуре типы, но тем не менее существует возможности для отдельных видов списков преобразования их в словарь с помощью встроенной функции dict() . Для этого список должен хранить набор вложенных списков. Каждый вложенный список должен состоять из двух элементов - при конвертации в словарь первый элемент станет ключом, а второй - значением:
users_list = [ ["+111123455", "Tom"], ["+384767557", "Bob"], ["+958758767", "Alice"] ] users_dict = dict(users_list) print(users_dict) #
Подобным образом можно преобразовать в словарь двухмерные кортежи, которые в свою очередь содержать кортежи из двух элементов:
users_tuple = ( ("+111123455", "Tom"), ("+384767557", "Bob"), ("+958758767", "Alice") ) users_dict = dict(users_tuple) print(users_dict)
Получение и изменение элементов
Для обращения к элементам словаря после его названия в квадратных скобках указывается ключ элемента:
dictionary[ключ]
Например, получим и изменим элементы в словаре:
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" ># получаем элемент с ключом "+11111111" print(users["+11111111"]) # Tom # установка значения элемента с ключом "+33333333" users["+33333333"] = "Bob Smith" print(users["+33333333"]) # Bob Smith
Если при установки значения элемента с таким ключом в словаре не окажется, то произойдет его добавление:
users["+4444444"] = "Sam"
Но если мы попробуем получить значение с ключом, которого нет в словаре, то Python сгенерирует ошибку KeyError:
user = users["+4444444"] # KeyError
И чтобы предупредить эту ситуацию перед обращением к элементу мы можем проверять наличие ключа в словаре с помощью выражения ключ in словарь . Если ключ имеется в словаре, то данное выражение возвращает True:
key = "+4444444" if key in users: user = users[key] print(user) else: print("Элемент не найден")
Также для получения элементов можно использовать метод get , который имеет две формы:
- get(key) : возвращает из словаря элемент с ключом key. Если элемента с таким ключом нет, то возвращает значение None
- get(key, default) : возвращает из словаря элемент с ключом key. Если элемента с таким ключом нет, то возвращает значение по умолчанию default
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" >user1 = users.get("+55555555") print(user1) # Alice user2 = users.get("+33333333", "Unknown user") print(user2) # Bob user3 = users.get("+44444444", "Unknown user") print(user3) # Unknown user
Удаление
Для удаления элемента по ключу применяется оператор del :
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" >del users["+55555555"] print(users) #
Но стоит учитывать, что если подобного ключа не окажется в словаре, то будет выброшено исключение KeyError. Поэтому опять же перед удалением желательно проверять наличие элемента с данным ключом.
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" >key = "+55555555" if key in users: del users[key] print(f"Элемент с ключом удален") else: print("Элемент не найден")
Другой способ удаления представляет метод pop() . Он имеет две формы:
- pop(key) : удаляет элемент по ключу key и возвращает удаленный элемент. Если элемент с данным ключом отсутствует, то генерируется исключение KeyError
- pop(key, default) : удаляет элемент по ключу key и возвращает удаленный элемент. Если элемент с данным ключом отсутствует, то возвращается значение default
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" >key = "+55555555" user = users.pop(key) print(user) # Alice user = users.pop("+4444444", "Unknown user") print(user) # Unknown user
Если необходимо удалить все элементы, то в этом случае можно воспользоваться методом clear() :
users.clear()
Копирование и объединение словарей
Метод copy() копирует содержимое словаря, возвращая новый словарь:
users = students = users.copy() print(students) #
Метод update() объединяет два словаря:
users = users2 = users.update(users2) print(users) # print(users2) #
При этом словарь users2 остается без изменений. Изменяется только словарь users, в который добавляются элементы другого словаря. Но если необходимо, чтобы оба исходных словаря были без изменений, а результатом объединения был какой-то третий словарь, то можно предварительно скопировать один словарь в другой:
users3 = users.copy() users3.update(users2)
Перебор словаря
Для перебора словаря можно воспользоваться циклом for:
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" >for key in users: print(f"Phone: User: ")
При переборе элементов мы получаем ключ текущего элемента и по нему можем получить сам элемент.
Другой способ перебора элементов представляет использование метода items() :
users = < "+11111111": "Tom", "+33333333": "Bob", "+55555555": "Alice" >for key, value in users.items(): print(f"Phone: User: ")
Метод items() возвращает набор кортежей. Каждый кортеж содержит ключ и значение элемента, которые при переборе мы тут же можем получить в переменные key и value.
Также существуют отдельно возможности перебора ключей и перебора значений. Для перебора ключей мы можем вызвать у словаря метод keys() :
for key in users.keys(): print(key)
Правда, этот способ перебора не имеет смысла, так как и без вызова метода keys() мы можем перебрать ключи, как было показано выше.
Для перебора только значений мы можем вызвать у словаря метод values() :
for value in users.values(): print(value)
Комплексные словари
Кроме простейших объектов типа чисел и строк словари также могут хранить и более сложные объекты - те же списки, кортежи или другие словари:
users = < "Tom": < "phone": "+971478745", "email": "tom12@gmail.com" >, "Bob": < "phone": "+876390444", "email": "bob@gmail.com", "skype": "bob123" >>
В данном случае значение каждого элемента словаря в свою очередь представляет отдельный словарь.
Для обращения к элементам вложенного словаря соответственно необходимо использовать два ключа:
old_email = users["Tom"]["email"] users["Tom"]["email"] = "supertom@gmail.com" print(users["Tom"]) #
Но если мы попробуем получить значение по ключу, который отсутствует в словаре, Python сгенерирует исключение KeyError:
tom_skype = users["Tom"]["skype"] # KeyError
Чтобы избежать ошибки, можно проверять наличие ключа в словаре:
key = "skype" if key in users["Tom"]: print(users["Tom"]["skype"]) else: print("skype is not found")
Во всем остальном работа с комплексными и вложенными словарями аналогична работе с обычными словарями.
Словари
В языке программирования Python словари (тип dict ) представляют собой еще одну разновидность структур данных наряду со списками и кортежами. Словарь - это изменяемый (как список) неупорядоченный (в отличие от строк, списков и кортежей) набор элементов "ключ:значение".
"Неупорядоченный" – значит, что последовательность расположения пар не важна, в следствие чего обращение к элементам по индексам невозможно.
В других языках структуры, схожие со словарями, называются по-другому. Например, в Java подобный тип данных называется отображением.
Чтобы представление о словаре стало более понятным, проведем аналогию с обычным словарем, например, англо-русским. На каждое английское слово в таком словаре есть русское слово-перевод: cat – кошка, dog – собака, table – стол и т. д. Если англо-русский словарь описать с помощью Python, то английские слова можно сделать ключами, а русские – их значениями:
{'cat': 'кошка', 'dog': 'собака', 'bird': 'птица'>
Обратите внимание, что для определения словаря используются фигурные скобки. Синтаксис словаря на Питоне описывается такой схемой:
В словаре доступ к значениям осуществляется не по индексам, а по ключам, которые заключаются в квадратные скобки (по аналогии с индексами списков):
>>> a['cat'] 'кошка' >>> a['bird'] 'птица'
Словари, как и списки, являются изменяемым типом данных: позволительно изменять, добавлять и удалять элементы (пары "ключ:значение"). Изначально словарь можно создать пустым (например, d = <> ) и потом заполнить его элементами. Добавление и изменение имеет одинаковый синтаксис: словарь[ключ] = значение . Ключ может быть как уже существующим (тогда происходит изменение значения), так и новым (происходит добавление элемента словаря). Удаление элемента осуществляется с помощью встроенной оператора del языка Python.
>>> a = <> >>> a[1] = 2.34 >>> a[2] = 4.88 >>> a >>> a[1] = 3.01 >>> a >>> del a[2] >>> a
В словаре не может быть двух элементов с одинаковыми ключами. Однако могут быть одинаковые значения у разных ключей.
Ключом может быть любой неизменяемый тип данных. Значением – любой тип данных. Значения словарей вполне могут быть структурами, например, другими словарями или списками.
>>> nums = >>> person1 = >>> person1['data'][0] 4
Перебор элементов словаря в цикле for
Элементы словаря перебираются в цикле for также, как элементы других сложных объектов. Однако "по-умолчанию" извлекаются только ключи:
>>> nums >>> for i in nums: . print(i) . 1 2 3
Но по ключам всегда можно получить значения:
>>> for i in nums: . print(nums[i]) . one two three
С другой стороны у словаря как класса есть метод items() , который создает особую структуру, состоящую из кортежей. Каждый кортеж включает ключ и значение:
>>> n = nums.items() >>> n dict_items([(1, 'one'), (2, 'two'), (3, 'three')])
В цикле for можно распаковывать кортежи, таким образом сразу извлекая как ключ, так и его значение:
>>> for key, value in nums.items(): . print(key, 'is', value) . 1 is one 2 is two 3 is three
Методы словаря keys() и values() позволяют получить отдельно перечни ключей и значений. Так что если, например, надо перебрать только значения или только ключи, лучше воспользоваться одним из этих методов:
>>> v_nums = [] >>> for v in nums.values(): . v_nums.append(v) . >>> v_nums ['one', 'two', 'three']
Методы словаря
Кроме рассмотренных выше трех методов items() , keys() и values() словари обладают еще восемью. Это методы clear() , copy() , fromkeys() , get() , pop() , popitem() , setdefault() , update() .
Метод clear() удаляет все элементы словаря, но не удаляет сам словарь. В итоге остается пустой словарь:
>>> nums >>> nums.clear() >>> nums <>
Словарь – это изменяемый тип данных. Следовательно, как и список он передается в функцию по ссылке. Поэтому иногда, чтобы избежать нежелательного изменения глобального словаря его копируют. Это делают и с другими целями.
>>> n1 = >>> n2 = n1 >>> n3 = n1.copy() >>> n2['c'] = 3 >>> n1 >>> n2 >>> n3
Метод fromkeys() позволяет создать словарь из списка, элементы которого становятся ключами. Применять метод можно как классу dict , так и к его объектам:
>>> a = [1, 2, 3] >>> c = dict.fromkeys(a) >>> c >>> d = dict.fromkeys(a, 10) >>> d
Метод get() позволяет получить элемент по его ключу:
>>> nums.get(1) 'one'
Метод pop() удаляет из словаря элемент по указанному ключу и возвращает значение удаленной пары. Метод popitem() не принимает аргумента, удаляет элемент по принципу "последним вошел, первым вышел" и возвращает его в программу в виде кортежа (ключ, значение) .
>>> nums = >>> nums.pop(1) 'one' >>> nums >>> nums.popitem() (3, 'three') >>> nums
С помощью setdefault() можно добавить элемент в словарь:
>>> nums.setdefault(4, 'four') 'four' >>> nums
Равносильно nums[4] = 'four' , если элемент с ключом 4 отсутствует в словаре. Если он уже есть, то nums[4] = 'four' перезапишет старое значение, setdefault() – нет.
С помощью update() можно добавить в словарь другой словарь:
>>> nums.update() >>> nums
Также метод обновляет значения существующих ключей. Включает еще ряд особенностей.
Практическая работа
- Создайте словарь, связав его с переменной school , и наполните данными, которые бы отражали количество учащихся в разных классах (1а, 1б, 2б, 6а, 7в и т. п.). Внесите изменения в словарь согласно следующему: а) в одном из классов изменилось количество учащихся, б) в школе появился новый класс, с) в школе был расформирован (удален) другой класс. Вычислите общее количество учащихся в школе.
- Напишите функцию, которая принимает один словарь, и возвращает другой, в котором ключами являются значения из первого словаря, а значениями – соответствующие им ключи. Создайте словарь, передайте его в функцию. Выведите на экран исходный и "перевернутый" словари.
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
Д. П. Кириенко. Программирование на языке Python (школа 179 г. Москвы)
Обычные списки (массивы) представляют собой набор пронумерованных элементов, то есть для обращения к какому-либо элементу списка необходимо указать его номер. Номер элемента в списке однозначно идентифицирует сам элемент. Но идентифицировать данные по числовым номерам не всегда оказывается удобно. Например, маршруты поездов в России идентифицируются численно-буквенным кодом (число и одна цифра), также численно-буквенным кодом идентифицируются авиарейсы, то есть для хранения информации о рейсах поездов или самолетов в качестве идентификатора удобно было бы использовать не число, а текстовую строку.
Структура данных, позволяющая идентифицировать ее элементы не по числовому индексу, а по произвольному, называется словарем или ассоциативным массивом. Соответствующая структура данных в языке Питон называется dict .
Рассмотрим простой пример использования словаря. Заведем словарь Capitals , где индексом является название страны, а значением — название столицы этой страны. Это позволит легко определять по строке с названием страны ее столицу.
# Создадим пустой словать Capitals Capitals = dict() # Заполним его несколькими значениями Capitals['Russia'] = 'Moscow' Capitals['Ukraine'] = 'Kiev' Capitals['USA'] = 'Washington' # Считаем название страны print('В какой стране вы живете?') country = input() # Проверим, есть ли такая страна в словаре Capitals if country in Capitals: # Если есть - выведем ее столицу print('Столица вашей страны', Capitals[country]) else: # Запросим название столицы и добавив его в словарь print('Как называется столица вашей страны?') city = input() Capitals[country] = city
Итак, каждый элемент словаря состоит из двух объектов: ключа и значения. В нашем примере ключом является название страны, значением является название столицы. Ключ идентифицирует элемент словаря, значение является данными, которые соответствуют данному ключу. Значения ключей — уникальны, двух одинаковых ключей в словаре быть не может.
В жизни широко распространены словари, например, привычные бумажные словари (толковые, орфографические, лингвистические). В них ключом является слово-заголовок статьи, а значением — сама статья. Для того, чтобы получить доступ к статье, необходимо указать слово-ключ.
Другой пример словаря, как структуры данных — телефонный справочник. В нем ключом является имя, а значением — номер телефона. И словарь, и телефонный справочник хранятся так, что легко найти элемент словаря по известному ключу (например, если записи хранятся в алфавитном порядке ключей, то легко можно найти известный ключ, например, бинарным поиском), но если ключ неизвествен, а известно лишь значение, то поиск элемента с данным значением может потребовать последовательного просмотра всех элементов словаря.
Особенностью ассоциативного массива является его динамичность: в него можно добавлять новые элементы с произвольными ключами и удалять уже существующие элементы. При этом размер используемой памяти пропорционален размеру ассоциативного массива. Доступ к элементам ассоциативного массива выполняется хоть и медленнее, чем к обычным массивам, но в целом довольно быстро.
В языке Питон как ключом может быть произвольный неизменяемый тип данных: целые и действительные числа, строки, кортежи. Ключом в словаре не может быть множество, но может быть элемент типа frozenset : специальный тип данных, являющийся аналогом типа set , который нельзя изменять после создания. Значением элемента словаря может быть любой тип данных, в том числе и изменяемый.
Когда нужно использовать словари
- Подсчет числа каких-то объектов. В этом случае нужно завести словарь, в котором ключами являются объекты, а значениями — их количество.
- Хранение каких-либо данных, связанных с объектом. Ключи — объекты, значения — связанные с ними данные. Например, если нужно по названию месяца определить его порядковый номер, то это можно сделать при помощи словаря Num['January'] = 1; Num['February'] = 2; . .
- Установка соответствия между объектами (например, “родитель—потомок”). Ключ — объект, значение — соответствующий ему объект.
- Если нужен обычный массив, но при этом масимальное значение индекса элемента очень велико, но при этом будут использоваться не все возможные индексы (так называемый “разреженный массив”), то можно использовать ассоциативный массив для экономии памяти.
Создание словаря
Пустой словарь можно создать при помощи функции dict() или пустой пары фигурных скобок <> (вот почему фигурные скобки нельзя использовать для создания пустого множества). Для создания словаря с некоторым набором начальных значений можно использовать следующие конструкции:
Capitals = Capitals = dict(Russia = 'Moscow', Ukraine = 'Kiev', USA = 'Washington') Capitals = dict([("Russia", "Moscow"), ("Ukraine", "Kiev"), ("USA", "Washington")]) Capitals = dict(zip(["Russia", "Ukraine", "USA"], ["Moscow", "Kiev", "Washington"]))
Первые два способа можно использовать только для создания небольших словарей, перечисляя все их элементы. Кроме того, во втором способе ключи передаются как именованные параметры функции dict , поэтому в этом случае ключи могут быть только строками, причем являющимися корректными идентификаторами. В третьем и четвертом случае можно создавать большие словари, если в качестве аргументов передавать уже готовые списки, которые могут быть получены не обязательно перечислением всех элементов, а любым другим способом построены по ходу исполнения программы. В третьем способе функции dict нужно передать список, каждый элемент которого является кортежем из двух элементов: ключа и значения. В четвертом способе используется функция zip , которой передается два списка одинаковой длины: список ключей и список значений.
Работа с элементами словаря
Основная операция: получение значения элемента по ключу, записывается так же, как и для списков: A[key] . Если элемента с заданным ключом не существует в словаре, то возникает исключение KeyError . Другой способ определения значения по ключу — метод get : A.get(key) . Если элемента с ключом get нет в словаре, то возвращается значение None . В форме записи с двумя аргументами A.get(key, val) метод возвращает значение val , если элемент с ключом key отсутствует в словаре. Проверить принадлежность элемента словарю можно операциями in и not in , как и для множеств. Для добавления нового элемента в словарь нужно просто присвоить ему какое-то значение: A[key] = value . Для удаления элемента из словаря можно использовать операцию del A[key] (операция возбуждает исключение KeyError , если такого ключа в словаре нет. Вот два безопасных способа удаления элемента из словаря. Способ с предварительной проверкой наличия элемента:
if key in A: del A[key]
Способ с перехватыванием и обработкой исключения:
try: del A[key] except KeyError: pass
Еще один способ удалить элемент из словаря: использование метода pop : A.pop(key) . Этот метод возвращает значение удаляемого элемента, если элемент с данным ключом отсутствует в словаре, то возбуждается исключение. Если методу pop передать второй параметр, то если элемент в словаре отсутствует, то метод pop возвратит значение этого параметра. Это позволяет проще всего организовать безопасное удаление элемента из словаря: A.pop(key, None) .
Перебор элементов словаря
Можно легко организовать перебор ключей всех элементов в словаре:
for key in A: print(key, A[key])
Следующие методы возвращают представления элементов словаря. Представления во многом похожи на множества, но они изменяются, если менять значения элементов словаря. Метод keys возвращает представление ключей всех элементов, метод values возвращает представление всех значений, а метод items возвращает представление всех пар (кортежей) из ключей и значений. Соответственно, быстро проверить, если ли значение val среди всех значений элементов словаря A можно так: val in A.values() , а организовать цикл так, чтобы в переменной key был ключ элемента, а в переменной val было его значение можно так:
for key, val in A.items(): print(key, val)