Методы работы со словарями и генераторами словарей
Расскажем об особенностях словарей и генераторов словарей – минимум теории, максимум примеров плюс 10 задач для тренировки в конце статьи.
Словарь dict – структура данных, в которой информация хранится в виде хеш-таблицы (ассоциативного массива). В таком массиве каждый ключ сопоставлен с определенным значением:
my_dict = {'цвет': 'красный', 'размер': 'XS', 'цена': 650}
Питоновский словарь аналогичен HashMap в Java и Object в JavaScript.
Как создать словарь в Python: 6 способов
Пустой словарь создается с помощью фигурных скобок или функции dict():
info_dict = {}
my_dict = dict()
Словари с данными, как и в случае со списками, можно создавать несколькими способами.
Способ 1: Перечисление ключей и значений
Данные словаря перечисляются в виде пар ключ: значение
через запятую и заключаются в фигурные скобки:
car = {'модель': 'Audi A5 Sportback', 'цвет': 'красный', 'пробег': '100500 км'}
Способ 2: Создание словаря с помощью dict()
При использовании этого метода ключи и значения тоже придется определить вручную:
>>> my_dict = dict(name = 'Евгений', age = 28, position = 'Java-разработчик')
>>> print(my_dict)
{'name': 'Евгений', 'age': 28, 'position': 'Java-разработчик'}
Способ 3: Создание словаря с помощью zip() и dict()
Если есть два списка, в одном из которых хранятся ключи, а в другом – значения, словарь можно создать при помощи zip() и dict():
>>> keys = ['цвет', 'размер', 'количество', 'цена']
>>> values = ['синий', '35х45х60', 5, 2500]
>>> info = dict(zip(keys, values))
>>> print(info)
{'цвет': 'синий', 'размер': '35х45х60', 'количество': 5, 'цена': 2500}
Способ 4: Создание словаря из списка кортежей и кортежа списков
Если имеется список кортежей, в которых первый элемент служит ключом, а второй – значением, словарь можно сформировать с помощью dict():
>>> item = [('модель', 'Aura'), ('цвет', 'пурпурный'), ('наличие', 'на складе')]
>>> item_dict = dict(item)
>>> print(item_dict)
{'модель': 'Aura', 'цвет': 'пурпурный', 'наличие': 'на складе'}
Точно так же этот подход работает с кортежeм списков:
>>> employee= (['имя', 'Никита'], ['отчество', 'Сергеевич'], ['фамилия', 'Колобков'], ['возраст', 32])
>>> empl_dict = dict(employee)
>>> print(empl_dict)
{'имя': 'Никита', 'отчество': 'Сергеевич', 'фамилия': 'Колобков', 'возраст': 32}
Способ 5: Метод fromkeys()
Если нужно создать словарь, у всех ключей которого – одинаковые значения, можно воспользоваться методом fromkeys():
>>> new_dict = dict.fromkeys(['север', 'юг', 'восток', 'запад'], 0)
>>> print(new_dict)
{'север': 0, 'юг': 0, 'восток': 0, 'запад': 0}
Способ 6: Использование генератора словарей
Словари можно создавать на основе списков и строк. При этом одновременно можно проводить различные действия с числами и символами – математические операции, подсчет, сравнение и так далее:
>>> numbers = [2, 18, 5, 7, 2, 32, 6, 9, 4, 8, 9, 12, 14, 14]
>>> my_dict = {n: numbers.count(n) for n in numbers}
>>> print(my_dict)
{2: 2, 18: 1, 5: 1, 7: 1, 32: 1, 6: 1, 9: 2, 4: 1, 8: 1, 12: 1, 14: 2}
В генераторах можно использовать преобразование типов данных и условия:
>>> st = '12 31 4 53 6 7 4 90 8 7 56 3 42'
>>> my_dict = {n: int(n) * 2 for n in st.split() if int(n) % 2 == 0}
>>> print(my_dict)
{'12': 24, '4': 8, '6': 12, '90': 180, '8': 16, '56': 112, '42': 84}
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»
Особенности словарей
Начиная с Python 3.6, словари являются упорядоченными коллекциями – пары ключ: значение
хранятся в словаре в порядке добавления. В отличие от строк и списков, словари не поддерживают срезы и конкатенацию, а к элементу словаря нельзя обратиться по индексу – в качестве индексов в словарях выступают ключи:
>>> my_dict = {'фрукт': 'яблоко', 'цвет': 'красный', 'количество': '53 кг'}
>>> print(my_dict['цвет'], my_dict[' количество '])
красный 53 кг
Ключи в словаре не должны повторяться – если добавить в словарь ключ, идентичный существующему, Python сохранит только один ключ с последним значением:
>>> my_dict = {'цвет': 'красный', 'цвет': 'синий'}
>>> print(my_dict)
{'цвет': 'синий'}
В качестве ключей можно использовать все типы данных, которые относятся к неизменяемым: int, float, Boolean (True/False), frozenset, строки, кортежи. Нельзя использовать списки, обычные множества set и словари, поскольку они являются изменяемыми. При этом в качестве значения в словарях можно использовать данные любого типа, включая словари – такие словари называются вложенными:
>>> hr_info = {'сотрудник1': {'имя': 'Егор', 'должность': 'пентестер'},
'сотрудник2': {'имя': 'Михаил', 'должность': 'DevOps'},
'сотрудник3': {'имя': 'Татьяна', 'должность': 'фронтендер'}}
>>> print(hr_info['сотрудник2']['должность'])
DevOps
Методы словарей в Python 3
Словари поддерживают некоторые методы, общие с другими типами данных, и имеют несколько своих собственных. Рассмотрим общие и уникальные методы на примерах.
Длина словаря и принадлежность элемента:
>>> my_dict = {'товар': 'футболка', 'размер': 'XL', 'цвет': 'белый', 'количество': '560'}
>>> print(len(my_dict))
4
>>> print('есть на складе' if 'футболка' in my_dict else 'нет в наличии')
нет в наличии
Сумма ключей, максимальный и минимальный элементы
Функция sum() подсчитывает сумму ключей словаря и работает только в том случае, когда ключи являются числами:
>>> my_dict = {5: '50', 8: '90'}
>>> print(sum(my_dict))
13
Функции min() и max() работают для большинства типов данных:
>>> my_dict = {'напиток': 'яблочный сок', 'объем': '2 л', 'цена': 250, 'количество': '156'}
>>> print(min(my_dict), max(my_dict))
количество цена
>>> print(min(my_dict, key=len))
цена
Объединение словарей
Словари можно объединять – если в них есть одинаковые ключи, в полученном словаре значение будет взято из последнего словаря:
>>> my_dict1 = {'товар': 'куртка', 'размер': 'XL', 'цвет': 'черный'}
>>> my_dict2 = {'артикул': '35m', 'количество': 34, 'цвет': 'синий'}
>>> print({**my_dict1, **my_dict2})
{'товар': 'куртка', 'размер': 'XL', 'цвет': 'синий', 'артикул': '35m', 'количество': 34}
Сравнение словарей
Словари считаются одинаковыми, если в них совпадают и ключи, и значения:
>>> my_dict = {'марка': 'BMW', 'цвет': 'черный', 'автопилот': 'нет'}
>>> my_dict2 = {'марка': 'Audi', 'цвет': 'черный', 'автопилот': 'нет'}
>>> print(my_dict == my_dict2)
False
Получение ключей, значений и элементов
Для работы с ключами используется метод keys(), со значениями – values(), с парами – items():
>>> my_dict = {'напиток': 'чай', 'вес': 100, 'цена': 550, 'количество': 256}
>>> print(my_dict.values())
dict_values(['чай', 100, 550, 256])
>>> print(my_dict.keys())
dict_keys(['напиток', 'вес', 'цена', 'количество'])
>>> print(my_dict.items())
dict_items([('напиток', 'чай'), ('вес', 100), ('цена', 550), ('количество', 256)])
Добавление и изменение элементов
Для изменения значения какого-либо ключа используют оператор присваивания =
:
>>> my_dict = {'должность': 'разработчик', 'имя': 'Антон'}
>>> my_dict['имя'] = 'Евгений'
>>> print(my_dict)
{'должность': 'разработчик', 'имя': 'Евгений'}
Если же такого ключа в словаре еще нет, новый элемент будет добавлен автоматически:
>>> my_dict = {'должность': 'разработчик', 'имя': 'Евгений'}
>>> my_dict['фамилия'] = 'Егоров'
>>> print(my_dict)
{'должность': 'разработчик', 'имя': 'Евгений', 'фамилия': 'Егоров'}
Однако если обратиться к несуществующему элементу без присвоения ему значения, произойдет ошибка:
>>> my_dict = {'должность': 'разработчик', 'имя': 'Евгений', 'фамилия': 'Егоров'}
>>> print(my_dict['город'])
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
KeyError: 'город'
Получение значения по ключу – get()
Чтобы избежать появления показанной выше ошибки, используют метод get(), которому можно передать значение по умолчанию – оно выведется, если такого ключа в словаре нет:
>>> my_dict = {'должность': 'инженер', 'имя': 'Кирилл'}
>>> print(my_dict.get('зарплата', 'не указана'))
не указана
Получение значения и/или добавление элемента с setdefault()
Другой метод для получения значения – setdefault(). Он действует двумя разными способами:
1) Если указанный ключ уже есть в словаре – возвращает его значение (даже при наличии значения по умолчанию):
>>> my_dict = {'возраст': 25, 'имя': 'Роман'}
>>> print(my_dict.setdefault('возраст', 'не указан'))
25
2) Если ключа нет – вставляет элемент в словарь, возвращает значение:
>>> my_dict = {'возраст': 35, 'имя': 'Егор'}
>>> print(my_dict.setdefault('зарплата', 150000))
150000
>>> print(my_dict)
{'возраст': 35, 'имя': 'Егор', 'зарплата': 150000}
Дополнение словаря
Элементы одного словаря можно «обновить», дополнить элементами другого. В случае совпадения ключей, как и при показанном ранее объединении словарей, сохраняются значения второго словаря:
>>> my_dict1 = {'должность': 'инженер', 'имя': 'Роман'}
>>> my_dict2 = {'должность': 'врач', 'имя': 'Роман'}
>>> my_dict1.update(my_dict2)
>>> print(my_dict1)
{'должность': 'врач', 'имя': 'Роман'}
Удаление элементов словаря
Как и в случае со списками, удалять элементы из словарей можно несколькими способами:
del – удаляет элемент с заданным ключом:
>>> my_dict = {'жанр': 'триллер', 'рейтинг': 7.5, 'название': 'Опасные связи'}
>>> del my_dict['название']
>>> print(my_dict)
{'жанр': 'триллер', 'рейтинг': 7.5}
pop() – возвращает удаленное значение:
>>> my_dict = {'жанр': 'драма', 'рейтинг': 8.5, 'название': 'Зеленая миля'}
>>> фильм = my_dict.pop('название')
>>> print(фильм)
Зеленая миля
popitem() – удаляет последний добавленный элемент и возвращает его ключ: значение в виде кортежа:
>>> my_dict = {'жанр': 'фэнтези', 'рейтинг': 7.7, 'название': 'Властелин колец'}
>>> movie = my_dict.popitem()
>>> print(movie)
('название', 'Властелин колец')
clear() – удаляет все элементы словаря:
>>> my_dict = {'жанр': 'драма', 'рейтинг': 6.1, 'название': 'В сердце моря'}
>>> my_dict.clear()
>>> print(my_dict)
{}
Создание копии словаря
Копия словаря создается тем же методом, что и в случае со списками – с помощью copy():
>>> my_dict = {'жанр': 'фантастика', 'рейтинг': 8.8, 'название': 'Бегущий по лезвию бритвы'}
>>> new_dict = my_dict.copy()
>>> print(new_dict)
{'жанр': 'фантастика', 'рейтинг': 8.8, 'название': 'Бегущий по лезвию бритвы'}
Практика
Задание 1
Напишите программу, которая получает на вход две строки, и формирует из них словарь. Ключами служат слова из первой строки, значениями – целые числа из второй.
Пример ввода:
яблоки сливы груши персики манго киви апельсины
34 56 23 89 55 32 11
Вывод:
{'яблоки': 34, 'сливы': 56, 'груши': 23, 'персики': 89, 'манго': 55, 'киви': 32, 'апельсины': 11}
Решение:
keys = input().split()
values = map(int, input().split())
my_dict = dict(zip(keys, values))
print(my_dict)
Задание 2
Напишите программу, которая получает на вход строку чисел, разделенных пробелами, и формирует словарь, в котором ключами служат четные числа, а значениями – слово четное
.
Пример ввода:
45 6 8 23 21 87 65 45 38
Вывод:
{6: 'четное', 8: 'четное', 38: 'четное'}
Решение:
nums = map(int, input().split())
my_dict = {n: 'четное' for n in nums if n % 2 == 0}
print(my_dict)
Задание 3
Напишите программу, которая получает на вход строку и подсчитывает, сколько раз в ней встречается каждый символ (независимо от регистра). Результат нужно вывести без фигурных скобок.
Пример ввода:
Есть только один способ избежать критики: ничего не делайте, ничего не говорите и будьте никем.
Вывод:
е-11 с-3 т-7 ь-4 -14 о-9 л-2 к-4 д-3 и-10 н-6 п-1 б-3 з-1 ж-1 а-2 р-2 :-1 ч-2 г-3 й-1 ,-1 в-1 у-1 м-1 .-1
Решение:
st = input().lower()
my_dict = {i: st.count(i) for i in st}
print(*[str(k) + '-' + str(v) for k, v in my_dict.items()])
Задание 4
Напишите программу, которая получает 2 слова на разных строках и определяет, являются ли эти слова анаграммами.
Пример ввода 1:
меч
мяч
Вывод:
Нет
Пример ввода 2:
Минотавр
Норматив
Вывод:
Да
Решение:
word1, word2 = input().lower(), input().lower()
c = {k: word1.count(k) for k in word1}
d = {k: word2.count(k) for k in word2}
print ('Да' if c == d else 'Нет')
Задание 5
Напишите программу, которая получает строку текста и формирует из нее сначала список списков, а затем словарь, в котором первый элемент подсписка служит значением, а второй – ключом. Результат нужно вывести в столбик, без фигурных скобок.
Пример ввода:
красный, цвет; Gucci, бренд; 145000, цена; 3, количество
Вывод:
цвет: красный
бренд: Gucci
цена: 145000
количество: 3
Решение:
sp = [[i.split(', ')[0], i.split(',')[1]] for i in input().split('; ')]
my_dict = {k: v for v, k in sp}
result = '\n'.join(f'{k}: {v}' for k, v in my_dict.items())
print(result)
Задание 6
Напишите программу, которая формирует телефонный справочник из введенной пользователем строки, а затем выдает нужный номер по имени абонента. Если абонента с таким именем нет, нужно вывести Нет такого абонента
.
Пример ввода:
Маша (923)567-78-90; Саша (912)345-23-21; Егор (812)456-64-23
Маша
Вывод:
(923)567-78-90
Решение:
st = input().split('; ')
phones = {i.split()[0]:i.split()[1] for i in st}
name = input()
print(phones.get(name, 'Нет такого абонента'))
Задание 7
Напишите программу, которая:
- получает на вход две строки;
- формирует словарь, в котором ключи взяты из первой строки, а значения (целые числа) – из второй;
- выводит
Есть
, есть ли в словаре значения, равные 5, иНет
в противном случае.
Пример ввода:
яблоки груши апельсины лимоны киви
2 7 9 5 1
Вывод:
Есть
Решение:
sp1 = input().split()
sp2 = map(int, input().split())
my_dict = dict(zip(sp1, sp2))
print('Есть' if 5 in my_dict.values() else 'Нет')
Задание 8
Напишите программу, которая получает на вход целое число от 1 до 12, и выводит название месяца, порядковому номеру которого соответствует введенное число. Если пользователь ввел число, которое меньше или больше допустимого – вывести подсказку Введите число от 1 до 12
.
Пример ввода:
10
Вывод:
Октябрь
Решение:
months = {1: 'Январь', 2: 'Февраль', 3: 'Март', 4: 'Апрель',
5: 'Май', 6: 'Июнь', 7: 'Июль', 8: 'Август',
9: 'Сентябрь', 10: 'Октябрь', 11: 'Ноябрь', 12: 'Декабрь'}
num = int(input())
print(months.get(num, 'Введите число от 1 до 12'))
Задание 9
Напишите программу, которая:
- Принимает на вход 3 строки с названиями стран и расположенными в них городами.
- Получает от пользователя название города и выводит страну, в которой он находится.
Пример ввода:
Австрия Вена Инсбрук Линц Грац
Испания Барселона Мадрид Малага Севилья
Франция Париж Марсель Лион Ницца
Грац
Вывод:
Австрия
Решение:
my_dict = {k:v for _ in range(3) for k, *v in [input().split()]}
city = input()
Задание 10
Имеется следующий словарь:
numbers = {'dict1': [11, 20, 30, 17, 6, 24, 90, 15, 17],
'dict2': [21, 33, 40, 10, 29, 31, 90, 12],
'dict3': [52, 34, 20, 21, 44, 22, 10, 87],
'dict4': [22, 54, 29, 21, 70, 88, 99, 34],
'dict5': [21, 40, 29, 21, 19, 32, 68, 77],
'dict6': [14, 60, 70, 10, 55, 61, 84, 99],
'dict7': [45, 80, 12, 23, 42, 22, 37, 90],
'dict8': [13, 14, 15, 26, 48, 92, 36, 11],
'dict9': [12, 70, 18, 28, 18, 28, 53, 91],
'dict10': [29, 79, 18, 28, 18, 28, 32, 55]}
Напишите программу, которая удалит из значений словаря все четные числа.
Решение:
numbers = {key: [i for i in value if i % 2 != 0] for key, value in numbers.items()}
print(numbers)
Подведем итоги
Словари и генераторы словарей помогают в решении задач, связанных с подсчетом, множественным выбором, хранением и обработкой значений, описывающих свойства объектов.
Во многих случаях словари позволяют избежать использования многоуровневых условий if… elif… else
. В следующей статье будем изучать методы кортежей.