Чему научитесь
- Повторять действие столько раз, сколько нужно, а не сколько написано
- Разбираться в трёх формах range и не терять последнее число
- Перебирать числа отрезка вперёд и назад
- Печатать последовательность в одну строку
Как устроено занятие
Сначала разбор с примерами и короткими проверками понимания — они нужны, чтобы поймать непонятое сразу, а не через три темы.
Дальше 15 задач лестницей: разминка, основа, со звёздочкой. Занятие засчитывается, когда решено 10 — остальные не пропадают и учитываются отдельно.
После занятия — вторая часть, ещё 15 задач на те же приёмы в новых сюжетах.
Сколько это займёт
Примерно час-полтора вместе с задачами. Сроков нет: можно закрыть вкладку и вернуться когда удобно — прогресс сохранится.
Когда одного раза мало
Задача: вывести числа от 1 до пяти. Тем, что вы умеете, это пишется так:
print(1)
print(2)
print(3)
print(4)
print(5)
Работает. А теперь до тысячи — и подход разваливается. Не потому, что тысяча строк долго печатать, а потому, что число заранее неизвестно: оно приходит во входных данных.
Значит нужна конструкция, которая говорит: «повтори это столько раз, сколько надо». В Python она называется цикл, и сегодня мы разберём первый из двух — for.
for i in range(1, 6):
print(i)
Пять строк превратились в две, а вместо пятёрки может стоять переменная. Читается так: «для каждого i из промежутка от 1 до 6 — напечатать i».
Как устроен range
range задаёт последовательность целых чисел. У него три формы, и путаница между ними — источник половины ошибок на этом занятии.
| запись | что перебирает | пример |
|---|---|---|
range(n) |
от 0 до n−1 | range(5) → 0 1 2 3 4 |
range(a, b) |
от a до b−1 | range(2, 6) → 2 3 4 5 |
range(a, b, k) |
от a с шагом k, не доходя до b | range(1, 10, 3) → 1 4 7 |
Правая граница никогда не входит. Это главное, что нужно запомнить. Чтобы перебрать числа от 1 до n включительно, пишут range(1, n + 1) — с прибавленной единицей.
Выглядит неудобно ровно до того момента, когда начинаешь перебирать элементы по номерам: там нумерация с нуля и правая граница вне промежутка оказываются очень кстати. Пока просто примите как правило: включить границу — прибавить единицу.
Шаг может быть отрицательным — тогда перебор идёт назад:
for i in range(5, 0, -1):
print(i) # 5 4 3 2 1
Здесь тоже правая граница не входит: ноль не напечатается.
Проверка: границы range
Сколько раз выполнится тело цикла for i in range(3, 8):?
Тело цикла и отступ
Как и у развилки, у цикла есть тело — строки, которые повторяются. Определяется оно отступом:
for i in range(1, 4):
print("шаг", i) # повторяется
print("---") # тоже повторяется
print("конец") # выполнится один раз
Выведется шесть строк из цикла и одна после. Сдвиньте последнюю строку вправо — и «конец» напечатается трижды. Отступ здесь не оформление, а часть смысла.
Переменная цикла — обычная переменная, ей можно пользоваться внутри как угодно: сравнивать, умножать, проверять на чётность. Именно это и делает цикл полезным:
n = int(input())
for i in range(1, n + 1):
if i % 3 == 0:
print(i)
Эта программа печатает все числа до n, делящиеся на три. Условие из прошлых занятий работает внутри цикла точно так же, как снаружи.
Как печатать в одну строку
Обычный print переводит строку после каждого вызова. Если в условии просят вывести числа через пробел в одной строке, нужен дополнительный аргумент:
for i in range(1, 6):
print(i, end=" ") # 1 2 3 4 5
end=" " означает «после значения поставь пробел, а не перевод строки». По умолчанию там как раз перевод строки.
Лишний пробел в конце строки проверяющую систему не смущает — она сравнивает по словам. А вот перевод строки вместо пробела уже сделает вывод другим.
Есть и второй способ — собрать всё в одну переменную и напечатать разом, но для него нужны строки и списки, до которых мы дойдём в третьем модуле. Пока хватит end.
Проверка: сколько итераций
Сколько раз выполнится тело цикла for i in range(0, 10, 3):? Введите целое число.
Три ошибки этого занятия
Забытая единица. range(1, n) вместо range(1, n + 1) — и последнее число теряется. Самая частая ошибка темы, и заметна она только на границе: программа работает почти правильно, что хуже, чем совсем неправильно.
Не тот отступ. Строка, которая должна выполняться один раз, оказалась внутри цикла — или наоборот. Признак: ответ печатается несколько раз вместо одного.
Отрицательный шаг без нужды. range(n, 0) не переберёт ничего: без третьего аргумента шаг равен единице, а идти от большего к меньшему единицей нельзя. Нужен range(n, 0, -1).
Как проверять себя
Для циклов есть быстрый способ: посчитайте, сколько раз выполнится тело, и сравните с тем, сколько должно. Для range(a, b) это ровно b - a раз.
И проверяйте на самых маленьких входах: n = 1 ловит почти все ошибки с границами. Если при единице программа не печатает ничего или печатает два числа — ошибка уже найдена.
Практика: пятнадцать задач
Лестница прежняя: пять разминочных, семь основных, три со звёздочкой. Зачёт при десяти решённых.
В части задач нужно вывести последовательность, в части — посчитать одно число. Во втором случае вам понадобится переменная, которая копит результат по ходу цикла — это и будет темой следующего занятия, а пока достаточно интуиции: заведите переменную до цикла и меняйте её внутри.
Ограничения в задачах на печать намеренно небольшие: выводить миллион чисел незачем, задача от этого не становится интереснее.
Почему пропало последнее число
Задача: «выведите числа от 1 до n включительно».
Ученик написал:
n = int(input())
for i in range(1, n):
print(i, end=" ")
На входе 5 программа печатает 1 2 3 4, а должна 1 2 3 4 5. Объясните, почему так происходит, что будет при , и как исправить.