EduBrick
классная работа

Цикл for и range

Программирование на Python: от нуля до олимпиад

0/18решено 0 из 18до зачёта осталось 10

Чему научитесь

  • Повторять действие столько раз, сколько нужно, а не сколько написано
  • Разбираться в трёх формах 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. Объясните, почему так происходит, что будет при n=1n = 1, и как исправить.

Войдите, чтобы ответить.