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 dict==>keys dict===>values key1-.->val1 key2-.->val2 key3-.->val3
Занятие № 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)
Примеры
Пример № 1 (ex01.py)
Создайте программу-переводчик, которая хранит перевод слов с русского языка на английский. После запуска программа выводит список слов в словаре и предлагает пользователю ввести слово для перевода. Если введенного слова нет в словаре выводится сообщение.
d = { "молоко": "milk", "хлеб": "bread", "вода": "water" } print("Слова в словаре") for key in d: print(key) word = input("Какое слово перевести? ") if word in d: print("Перевод:", d[word]) else: print("Такого слова нет в словаре")
Слова и перевод хранятся в переменной типа dict
под именем
x
?
. В этом словаре уже находятся
x
?
пары ключ-значение. С помощью цикла
for
выводим на экран список
x
ключей словаря d
. С помощью оператора
x
in
проверяем, есть ли среди ключей словаря d
введённое слово.
Пример № 2 (ex02.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
На каждом шаге цикла for
создаём пустой словарь student
. С помощью метода
x
update()
заполняем словарь student
введёнными с клавиатуры значениями. Метод
x
append()
добавит в конец списка ссылку на объект с информацией об очередном студенте.
Пример № 3 (ex03.py)
Пользователь вводит с клавиатуры строку с текстом. Программа должна подсчитать, сколько раз в тексте встречается каждое из слов. Слова в тексте разделяются пробелом, могут присутствовать знаки препинания (точка, запятая, знак вопроса, восклицательный знак).