graph LR
var[eng2rus]==>|=|dict
subgraph dict [Словарь]
direction LR
subgraph keys [Ключи]
key1([one])
key2([cat])
key3([mouse])
end
subgraph values [Значения]
val1(один)
val2(кот)
val3(мышь)
end
end
key1-.->val1
key2-.->val2
key3-.->val3
classDef varStyle fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e
classDef dictStyle fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a8a
classDef keyStyle fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#713f12
classDef valStyle fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#581c87
classDef subStyle fill:#f8fafc,stroke:#94a3b8,stroke-width:2px,stroke-dasharray:4
class var varStyle
class dict dictStyle
class keys,values subStyle
class key1,key2,key3 keyStyle
class val1,val2,val3 valStyle
Занятие № 8. Применение словарей для решения задач
Цель: научиться применять словари для решения задач.
Теория
Объявление словаря
Словарь (ассоциативный массив) – это набор ключей и соответствующих им значений. Данные в словаре не упорядочены. Словарь относится к изменяемым типам данных: можно добавлять новые значения и менять уже имеющиеся. В Python словарю соответствует тип dict.
Для описания словаря используются фигурные скобки:
В качестве примера опишем словарь eng2rus, который будет содержать перевод трёх слов с английского языка на русский. Внутри [] записывается новый ключ и затем присваивается значение. С помощью [<ключ>] можно получить значение, которое соответствует ключу:
eng2rus = {}
eng2rus["one"] = "один"
eng2rus["cat"] = "кот"
eng2rus["mouse"] = "мышь"
print(eng2rus)
print(eng2rus["cat"]) # получаем значение по ключу "cat"
Рисунок 1 наглядно показывает связь между ключами и значениями внутри словаря.
Если элементы словаря известны, то их можно записать в момент объявления переменной. Внутри {} через запятую записываются пары ключ:значение:
eng2rus = {"one": "один", "cat": "кот", "mouse": "мышь"}
print(eng2rus)
Ключами в словаре могут быть значению любого неизменяемого типа: int, float, str. Значения, хранимые в словаре, могут иметь любой тип.
# целочисленный ключ, строковое значение
num_names={1:"Один", 2: "Два", 3:"Три"}
# вещественный ключ, строковое значение
dec_names={1.5:"Одна целая, пять десятых", 2.5: "Два с половиной"}
# строковый ключ, целочисленное значение
roman_nums = {'I':1, 'II':2, 'III':3, 'IV':4, 'V':5}
# строковый ключ, значение - список
shop = {'фрукты': ['ананас', 'банан'], 'овощи': ['огурец', 'капуста']}В последнем примере в словаре shop в качестве значений выступают списки. Если записать выражение shop["фрукты"][1], то в результате мы получим строку
x
"банан".
Словарь - это неупорядоченная последовательность пар ключ-значение.
Верно. Порядок хранения ключей в словаре не обязательно совпадает с порядком их добавления.
Элементы словаря не упорядочены. В отличие от списков, пары ключ-значение в словаре не имеют порядкового номера.
Что будет выведено на экран после выполнения следующего кода:
Верно. Ключ мышь соответствует значению 6.
С этим значением ассоциируется ключ кот.
С этим значением ассоциируется ключ слон.
С помощью оператора [] можно получить из словаря значение по его ключу.
Удалить пару ключ-значение можно с помощью оператора del:
num_names={1:"Один", 2: "Два", 3:"Три"}
print(num_names)
del num_names[3]
print(num_names)
Что будет выведено на экран после выполнения следующего кода:
Верно. Мы складываем значения, которые хранятся по ключам тетрадь и ручка (12 + 6) и сохраняем результат в словаре под новым ключом заказ.
С этим значением ассоциируется ключ тетрадь.
Ключ заказ будет хранить сумму двух значений.
Так как новый ключ появляется слева от инструкции присваивания, то такой ключ будет создан в словаре.
Операторы in и not in
С помощью оператора in можно проверить, есть ли заданный ключ в словаре:
student = {"имя":"Павел", "возраст": 20, "отметка": 9}
# есть ли ключ "возраст" в словаре student
print("возраст" in student)
print("фамилия" in student)
print("отметка" not in student)
Методы класса dict
Класс dict содержит ряд методов для изменения словаря:
dict
| Метод | Значение |
|---|---|
<словарь>.get(<ключ>)<словарь>.get(<ключ>, <значение>) |
Если в словаре есть <ключ> - получить его значение, иначе вернуть <значение> |
<словарь_1>.update(<словарь_2>) |
Обновить содержимое <словарь_1> парами ключ-значение из <словарь_2> |
<словарь>.keys() |
Получить список ключей |
<словарь>.values() |
Получить список значений |
<словарь>.items() |
Получить список пар (ключ, значение) |
Рассмотрим некоторые из методов подробнее.
Если попытаться получить значение по ключу, которого нет в словаре, то возникнет ошибка времени выполнения:
student = {"имя":"Павел", "возраст": 20, "отметка": 9}
print(student["фамилия"])
Один из вариантов, как избежать ошибки - проверить наличие ключа с помощью оператора in:
student = {"имя":"Павел", "возраст": 20, "отметка": 9}
if "фамилия" in student:
print(student["фамилия"])
else:
print("Фамилия не указана")
Логическое выражение "фамилия" in student будет равно
x
?
, если ключ "фамилия" есть в словаре student.
Но лучше использовать метод get(). Независимо от того, есть ли нужный ключ в словаре или нет, метод всегда вернёт значение и не вызовет ошибку:
student = {"имя":"Павел", "возраст": 20, "отметка": 9}
print(student.get("фамилия"))
print(student.get("возраст"))
print(student.get("курс", 1)) # если ключа "курс" нет, вернуть 1
Когда ключа в словаре нет, метод get() вернёт значение None. В методе можно указать, какое значение возвращать, если ключ не существует. В случае со словарём student, результатом выражения student.get("отметка", 10) станет значение
x
?
.
Что будет выведено на экран после выполнения следующего кода:
Верно. Метод get() вернёт числа, которые хранятся по ключам тетрадь и ручка. Затем в переменную answer запишется значение выражения 12 // 2.
Мы делим 12 на 6 а не наоборот
В переменную answer записывается результат целочисленного деления, который не может быть строкой.
Оператор целочисленного деления // применяется к значениям, которые вернёт метод get(), а не к самому словарю.
Метод update() помогает быстро обновить содержимое словаря и добавить новые пары ключ-значение:
student = {"имя":"Павел", "возраст": 20, "отметка": 9}
print(student)
student.update({"фамилия": "Иванов"})
print(student)
student.update({"отметка": 10})
print(student)
Перебор ключей и значений словаря
Чтобы перебрать элементы словаря используем цикл for:
roman_nums = {'I':1, 'II':2, 'III':3, 'IV':4, 'V':5}
print(list(roman_nums.keys()))
for key in roman_nums.keys():
print(key, roman_nums[key])
Метод keys() возвращает последовательность ключей словаря. С помощью цикла перебираем данную последовательность. На каждой итерации цикла переменной key будет присваиваться очередной ключ. Обратите внимание, что ключи не обязательно перебираются в той же последовательности в какой они записаны в коде программы.
Вызов метода keys() можно пропустить. Цикл for по умолчанию будет перебирать ключи словаря:
roman_nums = {'I':1, 'II':2, 'III':3, 'IV':4, 'V':5}
for key in roman_nums:
print(key)
Метод values() возвращает последовательность значений словаря:
roman_nums = {'I':1, 'II':2, 'III':3, 'IV':4, 'V':5}
for value in roman_nums.values():
print(value)
Метод items() возвращает список пар ключ-значение. Эти пары значений сохраняются в типе tuple - кортеж.
roman_nums = {'I':1, 'II':2, 'III':3, 'IV':4, 'V':5}
for key, value in roman_nums.items():
print(key, value)
Кортежи можно использовать для позиционного присваивания:
a, b = 1, 2 print(a, b)
Если слева от присваивания находится кортеж, и последовательность справа от = содержит столько же элементов что и кортеж, значения из последовательности распакуются в кортеж слева. Выше показан пример позиционного присваивания. Таким же образом можно распаковать значения из списка:
temp = [21, 18, 19] m, t, w = temp print(m, t, w)
Разминка
Запишите результаты выполнения строк кода для словаря из вашего варианта.
print(cities['Минск']) ↪︎︎
x
?
print(974 in cities) ↪︎︎
x
?
print(cities.get('Витебск', 0)) ↪︎︎
x
?
print(cities.get('Брест', -1)) ↪︎︎
x
?
print(physics_constants['c']) ↪︎︎
x
?
print(9.8 in physics_constants) ↪︎︎
x
?
print(physics_constants.get('g', 0)) ↪︎︎
x
?
print(physics_constants.get('pi', 3.14)) ↪︎︎
x
?
print(ports['HTTPS']) ↪︎︎
x
?
print('HTTP' in ports) ↪︎︎
x
?
print(ports.get('SSH', 0)) ↪︎︎
x
?
print(ports.get('FTP', 21)) ↪︎︎
x
?
print(particles['n']) ↪︎︎
x
?
print('photon' in particles) ↪︎︎
x
?
print(particles.get('e', 0)) ↪︎︎
x
?
print(particles.get('mu', 0)) ↪︎︎
x
?
print(consts['pi']) ↪︎︎
x
?
print('e' in consts) ↪︎︎
x
?
print(consts.get('phi', 0)) ↪︎︎
x
?
print(consts.get('tau', 6.28)) ↪︎︎
x
?
print(cities['Гомель']) ↪︎︎
x
?
print('Брест' in cities) ↪︎︎
x
?
print(cities.get('Минск', 0)) ↪︎︎
x
?
print(cities.get('Брест', 350)) ↪︎︎
x
?
print(status[404]) ↪︎︎
x
?
print(200 in status) ↪︎︎
x
?
print(status.get(500, 'Unknown')) ↪︎︎
x
?
print(status.get(301, 'Redirect')) ↪︎︎
x
?
print(units['Давление']) ↪︎︎
x
?
print('Энергия' in units) ↪︎︎
x
?
print(units.get('Сила', 'None')) ↪︎︎
x
?
print(units.get('Энергия', 'Джоуль')) ↪︎︎
x
?
print(funcs['cos']) ↪︎︎
x
?
print('sin' in funcs) ↪︎︎
x
?
print(funcs.get('tan', '*')) ↪︎︎
x
?
print(funcs.get('cot', 'котангенс')) ↪︎︎
x
?
print(lakes['Освейское']) ↪︎︎
x
?
print('Браславские' in lakes) ↪︎︎
x
?
print(lakes.get('Нарочь', 0)) ↪︎︎
x
?
print(lakes.get('Долгое', 30)) ↪︎︎
x
?
print(ram['DDR4']) ↪︎︎
x
?
print('DDR3' in ram) ↪︎︎
x
?
print(ram.get('DDR5', 0)) ↪︎︎
x
?
print(ram.get('DDR2', 2007)) ↪︎︎
x
?
print(temps['таяние льда']) ↪︎︎
x
?
print('комнатная' in temps) ↪︎︎
x
?
print(temps.get('кипение воды', 0)) ↪︎︎
x
?
print(temps.get('комнатная', 20)) ↪︎︎
x
?
print(shapes['квадрат']) ↪︎︎
x
?
print('треугольник' in shapes) ↪︎︎
x
?
print(shapes.get('пятиугольник', 0)) ↪︎︎
x
?
print(shapes.get('шестиугольник', 6)) ↪︎︎
x
?
print(reserves['Припятский']) ↪︎︎
x
?
print('Полесский' in reserves) ↪︎︎
x
?
print(reserves.get('Березинский', 0)) ↪︎︎
x
?
print(reserves.get('Полесский', 1988)) ↪︎︎
x
?
Примеры
Пример № 1 (ex01.py)
Создадим программу, которая будет хранить список пользователей и адреса электронной почты. Программа должна:
- Предложить ввод имени и email до тех пор пока не введено пустое значение для имени.
- Вывести на экран список всех введённых контактов.
- По введённому имени вывести email или сообщить, что такого пользователя нет.
Пример работы программы:
Имя > <{Игорь}> ++enter++
Email > <{ig@post.com}> ++enter++
Имя > <{Оля}> ++enter++
Email > <{helga@ml.org}> ++enter++
Имя > ++enter++
{'Игорь': 'ig@post.com', 'Оля': 'helga@ml.org'}
Игорь ig@post.com
Оля helga@ml.org
Имя ><{Оля}> ++enter++
Адрес: helga@ml.orgВвод значений и заполнение словаря
В начале объявим пустой словарь под именем book следующим образом:
x
book = {}. Ввод значений разместим в циклеwhile, который запустим на бесконечное повторение. После ввода имени, проверим пустое ли оно. Если пустое, то прервём цикл while инструкцией
x
break.
Решение задачи выглядит следующим образом:
Запустите и протестируйте частичное решение.
Вывод значений из словаря
Для вывода списка контактов используем цикл for. Перебирать в цикле будем ключи словаря book. Чтобы получить ключи словаря используем метод
x
keys(). Значение по его ключу из словаря получим с помощью
x
квадратных скобок.
Пример № 2 (ex02.py)
Создайте программу-переводчик, которая хранит перевод слов с русского языка на английский. После запуска программа выводит список слов в словаре и предлагает пользователю ввести слово для перевода. Если введенного слова нет в словаре выводится сообщение.
Слова и перевод хранятся в переменной типа dict под именем
x
?
. В этом словаре уже находятся
x
?
пары ключ-значение. С помощью цикла for выводим на экран список
x
ключей словаря d. С помощью оператора
x
in проверяем, есть ли среди ключей словаря d введённое слово.
Пример № 3 (ex03.py)
Создайте программу для хранения оценок студентов. Пользователь вводит количество студентов, после чего вводит их имена, фамилии и отметка за экзамен. После этого программа выводит список студентов.
n = int(input("Введите количество студентов: "))
stud_list = []
for x in range(n):
student = {} # создаём пустой словарь
name = input("Имя: ")
last_name = input("Фамилия: ")
mark = float(input("Отметка за экзамен: "))
student.update({
"name": name,
"last_name": last_name,
"mark": mark
})
stud_list.append(student)
print("Список студентов")
for student in stud_list:
print(student)В переменной с именем
x
будет храниться список студентов. Элементами списка будут словари. Информация о каждом студенте будет храниться в словаре, содержащем ключи name (имя), last_name (фамилия) и mark (отметка за экзамен).
graph LR
var[stud_list]-->|=|list[list]
list-->ind0
list-->ind1
ind0((0))-->|=|stud1
ind1((1))-->|=|stud2
subgraph stud1[dict]
key1([name])-->val1(Иван)
key2([last_name])-->val2(Петров)
key3([mark])-->val3(7)
end
subgraph stud2[dict]
key4([name])-->val4(Ольга)
key5([last_name])-->val5(Иванова)
key6([mark])-->val6(9)
end
classDef var fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e
classDef lst fill:#f0fdf4,stroke:#16a34a,color:#14532d
classDef idx fill:#f1f5f9,stroke:#475569,stroke-width:2px,color:#0f172a
classDef dict fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a8a
classDef key fill:#fef9c3,stroke:#ca8a04,color:#713f12
classDef str fill:#f3e8ff,stroke:#9333ea,color:#581c87
classDef int fill:#fff7ed,stroke:#ea580c,color:#7c2d12
class var var
class list lst
class ind0,ind1 idx
class stud1,stud2 dict
class key1,key2,key3,key4,key5,key6 key
class val1,val2,val4,val5 str
class val3,val6 int
На каждом шаге цикла for создаём пустой словарь student. С помощью метода
x
update() заполняем словарь student введёнными с клавиатуры значениями. Метод
x
append() добавит в конец списка ссылку на объект с информацией об очередном студенте.
Задания для самостоятельной работы
Задание № 1 (sam01.py)
Напишите программу, которая создаёт словарь ключами которого являются числа от 1 до n включительно, а значением будет ключ возведённый в квадрат. n вводится с клавиатуры. Выведите полученный словарь на экран.
Пример работы программы:
> <{5}> ++enter++
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}Составьте решение из предложенных инструкций.
sq = i ** 2
nums[i] = sq
print(nums)
nums = {}
col = int(input("> "))
for i in range(1, col + 1):
Задание № 2 (sam02.py)
Программа содержит словарь, с набором товаров и стоимостью одной единицы данного товара. Пользователь вводит с клавиатуры название товара и его количество. Программа должна вывести на экран общую стоимость покупки.
Дополнительный плюс, если будет проверка наличия товара.
Шаблон программы:
Примеры работы программы:
Название товара: <{карандаш}> ++enter++
Количество: <{10}> ++enter++
Общая стоимость: 40 руб.Название товара: <{блокнот}> ++enter++
Количество: <{2}> ++enter++
Такого товара нетin можно проверить, есть ли нужный ключ в словаре.
Задание № 3 (sam03.py)
Дан следующий словарь, описывающий инвентарь и характеристики персонажа игры:
Схематически структура словаря inv показана на рисунке:
flowchart LR
inv["📦 <b>inv</b><br><i>(dict)</i>"]
k1(["🔑 'золото'"])
k2(["🔑 'состояние'"])
k3(["🔑 'сумка'"])
inv --- k1
inv --- k2
inv --- k3
v_int["500"]
k1 --> v_int
subgraph state_dict["📦 Словарь (dict)"]
k_h(["🔑 'здоровье'"]) --> v_h["100"]
k_e(["🔑 'опыт'"]) --> v_e["50"]
end
k2 --> state_dict
subgraph bag_list["📋 Список (list)"]
i1["0: 'ксилофон'"]
i3["1: 'спальный мешок'"]
i4["2: 'буханка хлеба'"]
end
k3 --> bag_list
classDef dict fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a8a
classDef key fill:#fef9c3,stroke:#ca8a04,color:#713f12
classDef lst fill:#f0fdf4,stroke:#16a34a,color:#14532d
classDef str fill:#f3e8ff,stroke:#9333ea,color:#581c87
classDef int fill:#fff7ed,stroke:#ea580c,color:#7c2d12
class inv,state_dict dict
class k1,k2,k3,k_h,k_e key
class v_int,v_h,v_e int
class bag_list lst
class i1,i2,i3,i4 str
Выполните следующие модификации словаря inv, используя операторы и методы классов dict и list:
- Добавьте в словарь новый ключ
'карман', присвоив ему список:['ракушки', 'ягода', 'платок']. - Отсортируйте список по ключу
'сумка'в алфавитном порядке. - Увеличьте количество
'золота'на 50 единиц. - Уменьшите показатель
'здоровье'внутри вложенного словаря по ключу'состояние'на 10.
С помощью функции print() выведите на экран обновлённый словарь inv.
Задание № 4 (sam04.py)
Создайте игру-викторину по физике. Вопросы и ответы хранятся в словаре. Посчитайте количество правильных ответов и выведите его в конце игры.
Шаблон программы:
quiz = {
"Единица измерения силы в системе СИ?": "ньютон",
"Явление сохранения скорости при отсутствии внешних воздействий?": "инерция",
"Величина, равная отношению массы тела к его объёму?": "плотность",
"Частица с положительным зарядом в атомном ядре?": "протон",
"Физическая величина, измеряемая в герцах?": "частота"
}
# ваше решение задачиЗадание № 5 (sam05.py)
Дан словарь terms в котором ключи - это названия физических величин, а значения - их буквенные обозначения. Напишите программу, которая создаст новый словарь, поменяв местами ключи и значения в словаре terms. Выведите новый словарь функцией print().
Шаблон программы:
Пример работы программы:
{ "v": "Скорость", "m": "Масса", "t": "Время", "a": "Ускорение", "F": "Сила" }Задание № 6 (sam06.py)
Даны два словаря. Напишите программу, которая объединит эти словари. Если ключи встречаются в обоих исходных словарях, значения, которые хранятся по этим ключам складываются.
Пример работы программы:
Первый словарь: {'a': 100, 'b': 200, 'c':300}
Второй словарь: {'a': 300, 'b': 200, 'd':400}
Результат: {'a': 400, 'b': 400, 'd': 400, 'c': 300}Задание № 7 (sam07.py)
Пользователь вводит строку с текстом. Напишите программу, которая посчитает, сколько раз каждая буква встречается в строке.
Пример работы программы:
Введите текст: Вот это текст
в -> 1
о -> 2
т -> 4
э -> 1
е -> 1
к -> 1
с -> 1Дополнительный плюс, если большие и маленькие буквы не будут считаться отдельно; не будут подсчитываться пробелы.