Урок курса
Перебор словаря и вложенные структуры
Python для новичковВ прошлом уроке мы научились создавать словарь, читать значения по ключу, изменять и удалять пары. Теперь задача другая: пройтись по всему словарю в цикле. Python даёт для этого три метода — keys(), values() и items(). Начнём с первых двух.
Перебор ключей и значений: keys() и values()
Когда нужно обойти словарь целиком, первый вопрос — что именно нужно на каждом шаге: только ключи, только значения или и то, и другое сразу.
Метод keys() возвращает все ключи словаря. Цикл по ним выглядит так:
grades = {'Анна': 5, 'Боб': 4, 'Вера': 3}
for name in grades.keys():
print(name)
Вывод:
Анна Боб Вера
Есть нюанс: если написать просто for name in grades: без вызова .keys(), результат будет тот же — Python по умолчанию итерируется по ключам. Но явный .keys() делает код более читаемым, особенно когда важно подчеркнуть намерение.
Метод values() работает симметрично, но отдаёт значения:
for grade in grades.values():
print(grade)
Вывод:
5 4 3
Главное ограничение values(): внутри цикла нет доступа к ключу. Если потребуется знать, чья это оценка — этот метод не поможет. Используйте его только когда ключ действительно не нужен: например, чтобы посчитать сумму всех оценок или найти максимум.
print(sum(grades.values())) # 12
print(max(grades.values())) # 5
Оба метода возвращают специальные объекты-представления (dict_keys и dict_values), а не обычные списки. Для большинства задач это не важно — они прекрасно работают в for и с функциями вроде sum(). Но если понадобится индексация или срез, придётся обернуть в list(): list(grades.keys()).
Перебор пар ключ-значение через items()
Методы keys() и values() дают доступ лишь к одной стороне словаря за раз. Но чаще всего нужно и имя, и значение одновременно — например, чтобы вывести «Анна: 5». Именно для этого существует items().
Метод возвращает представление, где каждый элемент — это пара (ключ, значение). В цикле for эта пара автоматически распаковывается в две переменные:
grades = {'Анна': 5, 'Боб': 4, 'Вера': 3}
for name, grade in grades.items():
print(f'{name}: {grade}')
Вывод:
Анна: 5 Боб: 4 Вера: 3
Запись for name, grade in grades.items() работает потому, что Python распаковывает каждую пару точно так же, как распаковывает кортеж: два элемента — две переменные. Имена переменных здесь произвольные, но принято называть их по смыслу ключа и значения.
В отличие от keys() или values(), внутри цикла доступны обе части пары сразу — это и есть главное преимущество items(). Вы можете использовать name и grade независимо, строить f-строки, сравнивать, передавать в функции.
Практический критерий выбора прост:
- Нужны только ключи —
keys()(или простоfor k in d). - Нужны только значения —
values(). - Нужны и ключ, и значение —
items().
Словарь со списком в качестве значения и вложенный цикл
До сих пор значениями словаря были простые объекты — строки, числа. Но значением может быть и список. Это позволяет группировать несколько связанных элементов под одним ключом.
Пример: словарь учебных предметов, где к каждому предмету привязан список тем:
courses = {
'математика': ['алгебра', 'геометрия'],
'физика': ['механика', 'оптика']
}
Чтобы обратиться к конкретной теме, используется двойная индексация — сначала ключ словаря, затем индекс внутри списка:
print(courses['физика'][0]) # механика
Первая пара скобок достаёт список по ключу 'физика', вторая — берёт нулевой элемент из этого списка.
Когда нужно пройтись по всем предметам и их темам сразу, одного цикла не хватит. Внешний цикл перебирает пары предмет → список тем, внутренний — темы внутри каждого списка:
for subject, topics in courses.items():
for topic in topics:
print(f'{subject} — {topic}')
Вывод:
математика — алгебра математика — геометрия физика — механика физика — оптика
Здесь subject — это ключ (название предмета), topics — список тем, который был значением в словаре. На каждой итерации внешнего цикла переменная topics содержит очередной список, и внутренний for topic in topics проходит по его элементам.
Это двухуровневая итерация: количество шагов внутреннего цикла зависит от длины каждого конкретного списка-значения, а не фиксировано заранее. Если у одного предмета три темы, а у другого — пять, внутренний цикл выполнится соответствующее количество раз.
Такую структуру — словарь, где ключи это категории, а значения это списки элементов — используют часто: список покупок по категориям, сотрудники по отделам, тэги по статьям. Паттерн один и тот же: внешний for k, v in d.items(), внутренний for item in v.
Безопасная итерация: изменение словаря в цикле
Есть одна ловушка, в которую легко попасть, когда цикл по словарю становится чуть сложнее — например, нужно удалить какие-то ключи прямо в процессе обхода.
Представим: есть словарь оценок, и мы хотим удалить всех студентов с оценкой ниже 4:
grades = {'Анна': 5, 'Боб': 3, 'Вера': 4, 'Глеб': 2}
for name, grade in grades.items():
if grade < 4:
del grades[name] # ОШИБКА
Пython немедленно бросит RuntimeError: dictionary changed size during iteration. Причина в том, что grades.items() — это живое представление словаря, а не его копия. Изменить размер словаря (добавить или удалить ключ) во время итерации по нему запрещено: итератор теряет ориентацию и Python явно сигнализирует об этом.
Изменение значения у уже существующего ключа — другое дело, это разрешено. Ошибка возникает только при добавлении или удалении ключей.
Решение простое: итерироваться не по самому словарю, а по его копии. Для этого d.items() оборачивают в list():
grades = {'Анна': 5, 'Боб': 3, 'Вера': 4, 'Глеб': 2}
for name, grade in list(grades.items()):
if grade < 4:
del grades[name]
print(grades) # {'Анна': 5, 'Вера': 4}
list(grades.items()) создаёт обычный список пар на момент начала цикла. Этот список никак не связан с живым состоянием словаря — удаление ключей из grades на него не влияет, и цикл проходит спокойно до конца.
Аналогичная ситуация возникает при итерации по list(d.keys()) с последующим del d[k] внутри — логика та же: оборачиваем в list(), получаем снимок ключей.
Если нужно не удалять, а собрать отфильтрованный словарь, ещё удобнее словарный comprehension — но это уже следующий инструмент. Пока достаточно запомнить правило: изменяешь словарь внутри цикла — итерируйся по копии.
Задача 1
Что выведет следующий код?
d = {'x': 10, 'y': 20, 'z': 30}
for k, v in d.items():
print(k, v)
Задача 2
Посмотрите на код:
prices = {'хлеб': 50, 'молоко': 80, 'масло': 120}
total = 0
for v in prices.values():
total += v
print(total)
Что выведет программа?
Задача 3
Какой цикл корректно перебирает одновременно ключи и значения словаря student?
Задача 4
Что выведет следующий код?
menu = {'суп': ['борщ', 'уха'], 'салат': ['оливье']}
for dish, options in menu.items():
for option in options:
print(option)
Задача 5
Посмотрите на словарь:
library = {
'фантастика': ['Дюна', 'Марсианин'],
'детектив': ['Шерлок Холмс']
}
Какое выражение вернёт строку 'Марсианин'?
Задача 6
Что произойдёт при выполнении этого кода?
scores = {'Аня': 5, 'Борис': 3}
for name in scores:
if scores[name] < 4:
del scores[name]
Задача 7
Сводка по турниру
У вас есть словарь stats с результатами турнира.
Нужно перебрать его методом items() и вывести по одной строке для каждой пары ключ-значение в формате:
победы: 12ничьи: 4поражения: 3
Порядок строк должен совпадать с порядком ключей в словаре.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 8
Меню по категориям
У вас есть словарь menu с категориями блюд.
Нужно вывести каждую категорию и все блюда из неё в одной строке в формате:
завтрак: каша, чайобед: суп, котлета, компотужин: омлет
Категории должны идти в том же порядке, в котором они записаны в словаре. Сначала переберите словарь методом items(), а затем для списка блюд используйте вложенный цикл и соберите строку через запятую.
Выводите одну строку на каждую категорию. Лишний текст печатать не нужно.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 9
Убери слишком слабые лампы из плана
В файле уже задан словарь lights с названиями комнат и яркостью ламп.
Нужно удалить из словаря все пары, у которых значение меньше 3, а затем сохранить итоговый словарь в переменную lights.
Обязательно проходите по копии словаря, чтобы не получить ошибку изменения размера во время итерации.
В конце программы словарь должен содержать только комнаты с яркостью 3 и выше.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задачи к уроку
- Перебор вложенного словаря Python: меню по категориям
Выведите категории и блюда из вложенного словаря Python через items(). Задача на перебор коллекций с проверкой кода.
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
