dict: ключ и значение
- Создавать dict и читать значение по ключу
- Добавлять, обновлять и удалять пары ключ-значение
- Использовать
getсо значением по умолчанию, чтобы избежать KeyError - Перебирать словарь через keys, values и items и работать со списком словарей
Что мы изучим?
dict (Dictionary, словарь) — структура, которая хранит пары из ключа и значения. Вместо доступа по позиции ([0]) обращаются по имени (["name"]).
Зачем это нужно?
В tuple ("Dana", 24, "Haifa") нужно помнить, что позиция 1 — это возраст. При 15 полях это рецепт для багов. dict решает эту проблему:
student = {"name": "Dana", "age": 24, "city": "Haifa"}
student["age"] # clear and readabledict — пожалуй, самая важная структура на ближайшие недели:
- JSON (завтра): формат, в котором сохраняют файлы и пересылают информацию по сети. В Python он превращается в dict.
- Темы бэкенда и баз данных: каждый запрос и ответ в API — по сути dict.
{"id": 7, "name": "Dana"}. - Любую «запись» — пользователя, товар или заказ — удобно представлять как dict.
Объяснение с основ
Что такое dict?
- Каждый элемент — пара: ключ (Key) → значение (Value).
- Уникальные ключи — двух одинаковых ключей нет. Присваивание существующему ключу заменяет значение.
- Изменяемый (mutable).
- Сохраняет порядок вставки (начиная с Python 3.7).
- Ключ обычно
strилиint. Значение может быть любым: число, текст, список и даже другой dict.
В настоящем словаре вы ищете слово (ключ) и получаете определение (значение). Вы не ищете «определение на позиции 5000 в книге». В телефонной книге: имя → номер. Два человека не могут появиться под абсолютно одинаковым именем как отдельные записи. Новая запись с тем же именем заменяет предыдущую.
Синтаксис
# create
empty = {}
student = {"name": "Dana", "age": 24}
# read
student["name"] # "Dana" - KeyError if the key does not exist
student.get("email") # None - no error if missing
student.get("email", "N/A") # "N/A" - default value if missing
# add / update (same syntax!)
student["email"] = "dana@mail.com" # new key -> added
student["age"] = 25 # existing key -> updated
# delete
del student["email"] # delete a key (KeyError if missing)
age = student.pop("age") # delete and return the value
# check
"name" in student # True - checks KEYS, not values
len(student) # number of key-value pairs
# iterate
for key in student: # keys
for value in student.values(): # values
for key, value in student.items(): # pairs (tuples!)Первый пример кода
week-2/student_dict.py:
student = {"name": "Dana", "age": 24, "city": "Haifa"}
print("Name:", student["name"])
print("Age:", student["age"])
student["age"] = 25
student["email"] = "dana@mail.com"
print("Updated:", student)
del student["city"]
print("After delete:", student)
print("Has email?", "email" in student)
print("Phone:", student.get("phone", "not provided"))Вывод:
Name: Dana
Age: 24
Updated: {'name': 'Dana', 'age': 25, 'city': 'Haifa', 'email': 'dana@mail.com'}
After delete: {'name': 'Dana', 'age': 25, 'email': 'dana@mail.com'}
Has email? True
Phone: not providedРазбор кода построчно
| Строка | Объяснение |
|---|---|
{"name": "Dana", ...} | Ключ, двоеточие, значение. Пары разделяются запятыми. |
student["name"] | Чтение по ключу: значение "Dana". |
student["age"] = 25 | Ключ существует, поэтому значение обновляется. |
student["email"] = "..." | Ключа нет, поэтому он добавляется (в конец). Абсолютно тот же синтаксис! |
del student["city"] | Удаление всей пары. |
"email" in student | Проверяет, существует ли ключ. |
student.get("phone", "not provided") | Ключа нет, поэтому возвращается значение по умолчанию, без ошибки. |
Ещё один пример
Список словарей — самая распространённая структура для «настоящих» данных (таблица: каждый dict — строка). А также подсчёт с помощью dict. week-2/products.py:
products = [
{"id": 1, "name": "Laptop", "price": 3500, "category": "electronics"},
{"id": 2, "name": "Mouse", "price": 80, "category": "electronics"},
{"id": 3, "name": "Desk", "price": 900, "category": "furniture"},
{"id": 4, "name": "Chair", "price": 450, "category": "furniture"},
]
print("--- Catalog ---")
for product in products:
print(product["id"], product["name"], product["price"], "NIS")
expensive = []
for product in products:
if product["price"] > 500:
expensive.append(product["name"])
print("Over 500 NIS:", expensive)
count_by_category = {}
for product in products:
category = product["category"]
count_by_category[category] = count_by_category.get(category, 0) + 1
print("Count by category:", count_by_category)
for category, count in count_by_category.items():
print(category, "->", count, "products")Вывод:
--- Catalog ---
1 Laptop 3500 NIS
2 Mouse 80 NIS
3 Desk 900 NIS
4 Chair 450 NIS
Over 500 NIS: ['Laptop', 'Desk']
Count by category: {'electronics': 2, 'furniture': 2}
electronics -> 2 products
furniture -> 2 productsРазбор:
products— список, каждый элемент которого — dict.product["price"]= цена текущего товара в цикле.- Шаблон подсчёта:
count_by_category.get(category, 0) + 1. Если категории ещё нет в словаре,getвозвращает 0, а затем 0+1 = 1. Если она уже есть, вы получаете текущее количество и прибавляете 1. Этот шаблон встречается снова и снова. .items()— возвращает пары(key, value)в виде tuple, аfor category, count inраспаковывает их (распаковка из предыдущего урока).
dict внутри dict
Значение само может быть dict:
user = {
"name": "Dana",
"address": {"city": "Haifa", "street": "Herzl 10"},
"hobbies": ["chess", "running"],
}
print(user["address"]["city"]) # Haifa
print(user["hobbies"][0]) # chessОбращаются «слой за слоем»: user["address"] возвращает dict, а у него берут ["city"]. Это именно структура JSON.
Типичная ошибка
Ошибка 1: KeyError для несуществующего ключа.
student = {"name": "Dana"}
print(student["age"])KeyError: 'age'Исправление: student.get("age") (возвращает None), student.get("age", 0) (значение по умолчанию) или сначала проверить через if "age" in student:.
Ошибка 2: искать значение через in.
student = {"name": "Dana"}
print("Dana" in student)Falsein для dict проверяет ключи. Чтобы проверить значения: "Dana" in student.values().
Ошибка 3: опечатка в ключе, которая создаёт новый ключ вместо обновления.
student = {"name": "Dana", "age": 24}
student["Age"] = 25
print(student){'name': 'Dana', 'age': 24, 'Age': 25}Никакой ошибки! Просто добавился новый ключ "Age", а "age" остался 24. Ключи чувствительны к регистру. Это тихая Logical Error, поэтому держите имена ключей единообразными (snake_case).
Ошибка 4: список в качестве ключа.
locations = {[32, 35]: "Haifa"}TypeError: unhashable type: 'list'Ключ должен быть неизменяемым (Immutable). Если нужен ключ из нескольких значений, используйте tuple: {(32, 35): "Haifa"}. (Связь с неизменяемостью объясним в следующем уроке.)
Практика
Упражнения опираются только на то, что пройдено в этом уроке и в предыдущих. Сначала попробуйте сами, и только потом открывайте решение.
Упражнение 1: Карточка студента
Создайте словарь student с именем "Dana", возрастом 24 и городом "Haifa". Затем:
- Обновите возраст на 25.
- Добавьте email
"dana@mail.com". - Удалите город.
- Напечатайте словарь, а также телефон с помощью
getсо значением по умолчанию"none".
Ожидаемый вывод:
{'name': 'Dana', 'age': 25, 'email': 'dana@mail.com'}
noneПоказать решение
student = {"name": "Dana", "age": 24, "city": "Haifa"}
student["age"] = 25
student["email"] = "dana@mail.com"
del student["city"]
print(student)
print(student.get("phone", "none")){'name': 'Dana', 'age': 25, 'email': 'dana@mail.com'}
nonestudent["phone"] выбросил бы KeyError. get возвращает значение по умолчанию, когда ключа нет.
Упражнение 2: Подсчёт слов
Напишите функцию count_words(text), которая возвращает словарь: каждое слово (в нижнем регистре) → сколько раз оно встречается.
counts = count_words("the cat and the dog and THE bird")
print(counts)Ожидаемый вывод:
{'the': 3, 'cat': 1, 'and': 2, 'dog': 1, 'bird': 1}Показать решение
def count_words(text):
counts = {}
for word in text.lower().split():
counts[word] = counts.get(word, 0) + 1
return counts
counts = count_words("the cat and the dog and THE bird")
print(counts){'the': 3, 'cat': 1, 'and': 2, 'dog': 1, 'bird': 1}counts.get(word, 0) возвращает 0 для слова, которое ещё не посчитано, — так не нужен отдельный if для нового слова.
Упражнение 3: Список словарей
products = [
{"name": "Laptop", "price": 3500, "category": "electronics"},
{"name": "Mouse", "price": 80, "category": "electronics"},
{"name": "Desk", "price": 900, "category": "furniture"},
]- Напечатайте названия товаров, цена которых ниже 1000.
- Постройте словарь, который считает, сколько товаров в каждой категории, и напечатайте его.
Ожидаемый вывод:
Mouse
Desk
{'electronics': 2, 'furniture': 1}Показать решение
products = [
{"name": "Laptop", "price": 3500, "category": "electronics"},
{"name": "Mouse", "price": 80, "category": "electronics"},
{"name": "Desk", "price": 900, "category": "furniture"},
]
for product in products:
if product["price"] < 1000:
print(product["name"])
counts = {}
for product in products:
category = product["category"]
counts[category] = counts.get(category, 0) + 1
print(counts)Mouse
Desk
{'electronics': 2, 'furniture': 1}Упражнение 4: Перебор словаря
stock = {"apple": 12, "banana": 0, "cherry": 5}Переберите словарь через items() и напечатайте каждый товар и его количество. Для товара с количеством 0 напечатайте out of stock.
Ожидаемый вывод:
apple -> 12
banana -> out of stock
cherry -> 5Показать решение
stock = {"apple": 12, "banana": 0, "cherry": 5}
for name, quantity in stock.items():
if quantity == 0:
print(name, "->", "out of stock")
else:
print(name, "->", quantity)apple -> 12
banana -> out of stock
cherry -> 5items() возвращает пары из ключа и значения, а распаковка в цикле разделяет каждую пару на две переменные.
Упражнение 5: Вложенный словарь
user = {
"name": "Dana",
"address": {"city": "Haifa", "street": "Herzl"},
"hobbies": ["chess", "running"],
}Напечатайте город, первое хобби и добавьте хобби "music". В конце напечатайте список хобби.
Ожидаемый вывод:
Haifa
chess
['chess', 'running', 'music']Показать решение
user = {
"name": "Dana",
"address": {"city": "Haifa", "street": "Herzl"},
"hobbies": ["chess", "running"],
}
print(user["address"]["city"])
print(user["hobbies"][0])
user["hobbies"].append("music")
print(user["hobbies"])Haifa
chess
['chess', 'running', 'music']Каждые [ ] уходят на уровень глубже: user["address"] — словарь, а ["city"] достаёт из него значение. Это именно структура JSON.
Итоги
- dict
{key: value}— доступ по ключу, а не по позиции. Ключи уникальны. d[key] = value— добавляет, если ключ новый, обновляет, если он существует.d[key]выбрасываетKeyErrorдля отсутствующего ключа.d.get(key, default)не выбрасывает.inпроверяет ключи. Перебор:keys(),values(),items()(пары).- Список словарей = таблица. dict внутри dict = JSON.
- Шаблон подсчёта:
counts[x] = counts.get(x, 0) + 1.