Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 3 из 20 Начальный 15 мин 100 XP

Python цикл по строке, словарю и строкам файла

for ходит не только по спискам: строка — последовательность символов, словарь перебирается по ключам, а items отдаёт готовые пары. Плюс построчный перебор текста файла.

Редакция Питоники

До сих пор цикл for ходил по спискам и диапазонам. На деле список — лишь самый заметный обитатель большого семейства последовательностей: наборов, по которым можно идти элемент за элементом. Строка — последовательность символов. Словарь — последовательность ключей. Файл — последовательность строк. Цикл умеет ходить по всем — меняется только то, что попадает в переменную цикла на каждом шаге.

Строка: перебор символов

Строка в цикле распадается на отдельные символы: for ch in 'Кот' выполнит тело трижды — сначала ch равно 'К', потом 'о', потом 'т':

цикл по символам
for ch in 'Кот':
    print(ch)
Вывод
К
о
т

Переменную цикла для строк обычно называют ch — от character, символ. Пустая строка даст ноль шагов, как пустой список: перебирать нечего. С символом внутри тела можно делать всё то же, что со строкой: печатать, сравнивать, складывать в новые строки — ведь одиночный символ в Python тоже строка, просто длиной в один знак.

символ внутри f-строки
word = 'Кот'
for ch in word:
    print(f'{ch} — буква слова {word}')
Вывод
К — буква слова Кот
о — буква слова Кот
т — буква слова Кот

Словарь: цикл идёт по ключам

Словарь из раздела про словари — набор пар «ключ — значение». Цикл for по словарю перебирает ключи:

for по словарю — ключи
prices = {'молоко': 89, 'хлеб': 42, 'сыр': 590}

for name in prices:
    print(name)
Вывод
молоко
хлеб
сыр

В переменную цикла попадают ключи — названия товаров, а не цены. Пары идут в том порядке, в каком их вставили при создании словаря: молоко, хлеб, сыр. for по словарю перебирает ключи, а значения достаются по ключу внутри тела цикла. Зная ключ, значение достают обычным доступом по ключу — прямо в теле:

ключ из цикла, значение по ключу
prices = {'молоко': 89, 'хлеб': 42}

for name in prices:
    print(f'{name}: {prices[name]} р.')
Вывод
молоко: 89 р.
хлеб: 42 р.

Порядок пар в словаре

Отдельно стоит сказать про порядок. Начиная с Python 3.7 словарь сохраняет порядок вставки: ключи идут в том порядке, в котором вы их добавляли, а не в случайном порядке внутренней структуры. То, что в старых версиях считалось случайностью, теперь гарантируется языком.

ключи в порядке вставки
prices = {'сыр': 590, 'хлеб': 42, 'молоко': 89}
for name in prices:
    print(name, prices[name])
Вывод
сыр 590
хлеб 42
молоко 89

Словарь создан в порядке сыр, хлеб, молоко — и цикл выдал их ровно в таком порядке. На это можно опираться, когда важна предсказуемость вывода: отчёт, в котором позиции не должны прыгать от запуска к запуску, будет вести себя одинаково. Переприсвоение ключа, кстати, его позицию не меняет: новым значением заменяется только значение, ключ остаётся на своём месте.

items(): ключ и значение парой

Доставать значение по ключу вручную — рабочий, но двухходовый приём. Метод items() отдаёт циклу готовые пары: и ключ, и значение вместе. Пара — кортеж, и его удобно распаковать прямо в заголовке цикла, перечислив два имени через запятую:

распаковка пары в заголовке
prices = {'молоко': 89, 'хлеб': 42}

for name, price in prices.items():
    print(f'{name} стоит {price} рублей')
Вывод
молоко стоит 89 рублей
хлеб стоит 42 рублей

Распаковка работает так: на каждом шаге items() отдаёт кортеж из двух элементов, Python раскладывает его по двум переменным — ключ в name, значение в price. Если распаковку не писать, в переменную цикла попадёт весь кортеж целиком, и печать покажет его со скобками:

пара без распаковки
prices = {'чай': 30}

for pair in prices.items():
    print(pair)
Вывод
('чай', 30)

Скобки в выводе — верный признак кортежа: цикл отдал пару не разобранной. Двух имён в заголовке достаточно для пар из items(); больше двух элементов распаковываются так же — по числу имён. У словаря есть и метод values() — он перебирает одни значения без ключей: for price in prices.values().

Словарь внутри списка

В реальных данных почти всегда смесь: список словарей, словарь списков, словарь словарей. Цикл разбирает любую из этих конструкций, если выбрать правильный уровень. Начнём с самого частого случая — список заказов, где каждый заказ сам словарь.

заказы из списка словарей
orders = [
    {'name': 'Анна', 'total': 890},
    {'name': 'Борис', 'total': 1240},
]

for order in orders:
    print(order['name'], '-', order['total'])
Вывод
Анна - 890
Борис - 1240

Внешний цикл идёт по списку и достаёт словари — по одному за шаг. На этом шаге перед нами уже словарь, и к нему обращаются по ключу: order['name'], order['total']. Обратите внимание на квадратные скобки — это доступ по ключу, а не вызов функции. Именно так выглядит работа с данными из JSON: сначала список, потом словарь внутри, и два уровня цикла не нужны.

Обратная конструкция — словарь, у которого значения это списки. Тут всё наоборот: внешний цикл идёт по ключам, а по значению нужно пройти отдельным циклом.

словарь списков
stock = {'хлеб': [10, 12, 9], 'сыр': [5, 4]}
for goods, amounts in stock.items():
    print(goods, '- запас', amounts)
Вывод
хлеб - запас [10, 12, 9]
сыр - запас [5, 4]

Здесь items() отдал пары: название товара и список остатков по складам. Если понадобится пройти и по складам, добавляется второй цикл — получается вложенность, о которой подробно в уроке о вложенных циклах.

Строки файла

Файл на диске — тоже последовательность, и цикл по нему читает текст построчно. Запись для локального Python выглядит так:

цикл по строкам файла
menu = open('menu.txt', encoding='utf-8')
for line in menu:
    print(line.strip())
menu.close()
В браузерной песочнице файлов нет — этот блок для запуска на своём компьютере, где рядом с программой лежит menu.txt. В песочнице тот же приём работает на списке строк — следующий блок.

Файл открыт как menu, и цикл ходит по нему, как по списку: одна итерация — одна строка текста. Каждая строка файла заканчивается невидимым символом переноса \n — поэтому тело снимает его методом strip(), знакомым по уроку про strip. В песочнице вместо файла удобно взять многострочную строку и порезать её на список строк методом split — перебор получится тот же:

построчный перебор текста
menu = 'Каша\nЧай\nКомпот'

for line in menu.split('\n'):
    print(f'В меню: {line}')
Вывод
В меню: Каша
В меню: Чай
В меню: Компот

Лог построчно: считаем и печатаем

Самый частый случай из реальной работы — текстовый файл. В песочнице файлов нет, но приём тот же: разбиваем многострочный текст на список строк и идём по нему циклом. Сначала посчитаем, сколько записей в логе, потом пройдём по ним.

разбор лога
log = 'ошибка\nвход\nвыход'
lines = log.split('\n')
print('строк в логе:', len(lines))
for line in lines:
    print('-', line)
Вывод
строк в логе: 3
- ошибка
- вход
- выход

Метод split превращает один кусок текста в список кусочков — и сразу становится ясно, что циклу по файлу и циклу по списку строк нужен один и тот же код. Разница только в том, откуда взялся список: из файла он приходит сам, в песочнице его приходится собрать вручную.

перебор по числу
for n in 42:
    print(n)
Не запускается: TypeError: 'int' object is not iterable. Цикл for ходит по последовательностям. Одиночное число ею не является — нужен range(42).

По чему ходит for

ПоследовательностьЧто в переменной циклаПример заголовка
СписокЭлементfor name in names:
СтрокаСимволfor ch in word:
СловарьКлючfor name in prices:
dict.items()Пара ключ — значение (кортеж)for name, price in prices.items():
ФайлСтрока текста с \n на концеfor line in file:
  • перебор символов: посчитать буквы, найти цифры в номере, проверить каждый знак пароля;
  • перебор словаря: распечатать все пары настроек, обойти товары каталога;
  • построчный перебор: обработать лог, меню, CSV-файл — строка за строкой;
  • если вместе с элементом нужен его номер — например «1. молоко», — номер даёт enumerate: урок 4 целиком про него.

Последовательности разобраны: список, строка, словарь, файл. Остался счёт — номер шага, который хочется видеть рядом с элементом. Вручную он решается счётчиком, а по-настоящему — функцией enumerate, и следующий урок посвящён именно ей.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

for ch in 'Дом':
    print(ch)
d = {'a': 1, 'b': 2}

for k in d:
    print(k)
d = {'чай': 30, 'кофе': 80}

for name, price in d.items():
    print(name, price)
Проверь себя
0 / 9

1. Что попадает в переменную цикла при for ch in 'Дом'?

2. По чему идёт цикл for name in prices, если prices — словарь?

3. Что отдаёт метод items()?

4. Зачем при печати строк файла вызывают strip()?

5. Что напечатает for pair in prices.items() без распаковки?

6. Как в цикле по словарю напечатать и ключ, и значение?

7. В каком порядке цикл for перебирает словарь?

8. Что произойдёт при for n in 42: ?

9. Как пройти по списку словарей и достать из каждого поле?

Карточки терминов
Запомнено: 0 / 9
Практика

Строка menu содержит блюда через перенос строки: 'Борщ\nЧай\nКомпот'. Напечатай каждое блюдо отдельной строкой в формате «— Борщ».

practice.py
Вопросы и ответы по уроку

Как перебрать символы строки в Python?

Циклом for прямо по строке: for ch in 'Кот': print(ch) напечатает К, о, т — по символу на строку. Каждый одиночный символ — это строка длины 1, с ним работают все строковые методы.

По чему идёт цикл for по словарю?

По ключам: for name in prices перебирает названия, а не цены. Значение достаётся по ключу внутри тела (prices[name]), а метод items() отдаёт готовые пары — их распаковывают в заголовке: for name, price in prices.items().

Урок 1: словарь — ключ и значение

Как читать файл построчно циклом?

Открыть файл и перебрать его: for line in open('data.txt', encoding='utf-8'): print(line.strip()). Каждая итерация даёт одну строку с переносом \n на конце, который снимает strip(). В браузерной песочнице файл заменить многострочной строкой и split('\n').

Урок 6: strip — обрезаем края

Почему при печати строк файла появляются пустые строки?

Строка файла несёт невидимый перенос \n, а print добавляет второй — перенос удваивается. Пустые строки пропадают, если снять перенос strip() или напечатать line без print вовсе: print(line, end='') — но strip() читается яснее.

Как перебрать словарь и получить и ключ, и значение?

Метод items() отдаёт пары, которые распаковываются в заголовке: for name, price in prices.items(). Без распаковки в переменную попадёт кортеж целиком, и print покажет скобки.

Урок 2: range — цикл со счётчиком

В каком порядке идут ключи при переборе словаря?

В порядке вставки: с Python 3.7 это гарантия языка, а не случайность. Поэтому отчёты и логи выглядят одинаково от запуска к запуску, и на такой порядок можно опираться.

Понравился урок? Сошлитесь на него

«for по словарю перебирает ключи, а значения достаются по ключу внутри тела цикла.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.