Модуль 3 · Урок 3.2
Цикл for и диапазоны
for перебирает готовый набор значений; range задаёт числа с исключённой правой границей.
В прошлом уроке цикл while сам вёл счётчик: задавал начало, проверял границу, делал шаг. Так перебирают числа очень часто, и для этого в Python есть запись короче. for берёт значения из готового источника по одному, а range выдаёт нужные числа: начало, граница и шаг записываются в одном месте.
В примерах будем искать и считать кратные: первое кратное 17 среди чисел от 100 до 200, кратные 7 до 100.
Цикл for
for по очереди берёт значения источника и выполняет тело для каждого. Источник — то, из чего можно брать значения по одному, например строка или range:
for letter in "CODE": print(letter)На каждой итерации имя letter связывается с очередной буквой. Имя можно выбрать любое: letter — не команда. В отличие от while, здесь не нужно самому увеличивать номер и следить за границей: источник сам кончается.
for и while делают одно и то же повторение, просто for берёт счётчик на себя. Сравни две записи суммы 1 + 2 + 3 + 4:
while пишут вручную, в for лежит внутри range(1, 5): начало 1, граница 5 и шаг 1, который не пишут, — он подразумевается.range
range выдаёт целые числа от начала до границы с заданным шагом; сама граница в перебор не входит. У range три формы:
for i in range(4): print(i, end=" ")print()for i in range(2, 6): print(i, end=" ")print()for i in range(5, 0, -2): print(i, end=" ")range(4) — числа от 0 до 3: одно число — это граница, а начало по умолчанию 0. range(2, 6) — от 2 до 5. range(5, 0, -2) — от 5 вниз шагом 2: при отрицательном шаге перебор идёт, пока значение больше границы. Пустой print() переводит строку после каждого цикла.
Чтобы пройти числа от a до b включительно, пишут range(a, b + 1): например, от 1 до 100 — range(1, 101).
Тонкости:как устроен range
range не создаёт все числа заранее: он хранит начало, границу и шаг и выдаёт числа по одному, поэтому range(10 ** 9) не занимает памяти. Шаг 0 запрещён — ValueError. range(5, 0) пуст: шаг по умолчанию 1, а 5 уже не меньше 0. Исключённая граница удобна: в range(n) ровно n чисел, а range(0, k) и range(k, n) стыкуются без пересечения.
Здесь показан range(2, 9, 3): от 2 шагами по 3 получаются 2, 5 и 8, а следующее значение 11 уже не меньше 9; сама граница 9 в перебор не входит. Меняй start, stop и step — схема и список значений пересчитываются сразу.
Переменная цикла
Присваивание переменной цикла не меняет следующие значения for.
for i in range(3): print(i) i = 100Присваивание связывает имя i с 100 только до конца итерации. Следующая итерация снова берёт очередное число из range. Если правила перехода должны меняться по ходу, нужен while.
Вложенные циклы
Во вложенных циклах внутренний выполняется целиком для каждого значения внешнего. Так перебирают все пары: строки и столбцы таблицы, два числа из диапазона. Нажми «Запуск» и пройди по шагам:
for row in range(2): for column in range(3): print(row, column)Для каждого row внутренний цикл выполняется целиком: пары (0, 0), (0, 1), (0, 2), затем (1, 0), (1, 1), (1, 2). Всего 2 × 3 итерации внутреннего тела. break внутри него завершает только внутренний цикл.
column.Первое подходящее
Перебор по возрастанию с break находит наименьшее подходящее значение. Найдём первое число от 100 до 200, кратное 17:
answer = Nonefor n in range(100, 201): if n % 17 == 0: answer = n breakprint(answer)Перебор идёт по возрастанию, поэтому первое найденное число — наименьшее, и дальше искать незачем. Запись answer = None заранее говорит «ответа пока нет»: если подходящего числа не найдётся, программа напечатает None. Проверяют это записью answer is None.
Тонкости:is None и else у цикла
is проверяет, что это то же самое значение None, а не просто равное ему; для None так принято писать. У цикла бывает else: его блок выполняется, если цикл закончился без break, в том числе при нуле итераций. Поиск кратного 17 там, где его нет:
for n in range(103, 119): if n % 17 == 0: print(n) breakelse: print("нет")Шаг range
Шаг range позволяет перебирать только нужные числа. Найдём количество и сумму чисел от 1 до 100 включительно, кратных 7:
count = 0total = 0for n in range(1, 101): if n % 7 == 0: count += 1 total += nprint(count, total)То же можно перебрать сразу по кратным: range(7, 101, 7). Проверка не нужна, а цикл делает 14 итераций вместо 100. Такая замена верна, если понятно, почему она охватывает все нужные числа и только их: 7 — первое кратное, шаг 7 даёт каждое следующее, а следующее кратное, 105, уже больше 100.
Сквозная задача
Сквозная задача курса: сумма и наибольшее, когда количество чисел известно заранее. В прошлом уроке числа вводились до признака 0. Часто данные устроены иначе: сначала вводится, сколько будет чисел, затем сами числа. Тогда подходит for: он повторит ввод нужное число раз. Имя переменной цикла здесь не нужно, и его по соглашению называют _:
count = int(input())n = int(input())total = nbest = nfor _ in range(count - 1): n = int(input()) total += n if n > best: best = nprint(total, best)Первое число читаем до цикла — с него начинаются и сумма, и лучшее. Остальные count - 1 чисел читает цикл. Признак окончания больше не нужен, поэтому среди чисел может быть и ноль.
Три способа порядка строк
Порядок выполнения строк задают три основных способа. Модули «Старт», «Условия» и «Циклы» вместе дали всё, чем программа управляет своим ходом в первых задачах:
print, input выполняются сверху вниз по одной. Выбор: if, elif, else выполняют один блок из нескольких или ни одного. Повтор: while и for возвращаются к началу блока, пока условие истинно или есть значения.Программы курса — сочетания этих способов, вложенных друг в друга. Поэтому чтение незнакомого кода сводится к одному вопросу на каждой строке: какая строка выполнится следующей и какие значения у имён сейчас. Именно это показывает запуск примера по шагам: подсвеченная строка и значения переменных.
Итог
for и range берут счётчик на себя — так перебирают числа в большинстве задач курса и ЕГЭ. Вот что понадобится дальше.
for x in источникБерёт значения по одному; источник сам кончается.range(a, b, step)Отaдо границыb, не включая её; начало по умолчанию 0, шаг — 1. Отрицательный шаг идёт вниз.- ВключительноОт
aдоbвключительно —range(a, b + 1). - Вложенные циклыВнутренний выполняется целиком для каждого значения внешнего.
- Первое подходящееПеребор по возрастанию с
break; нет ответа —None. - Шаг
range(7, 101, 7)перебирает только кратные — без проверки. for _ in range(count)Повторить действие известное число раз.
Проверьте себя
Ответь сначала сам, потом открой ответ.
Какие числа дают range(3, 15, 4), range(10, 0, -3) и range(5, 5)?
ОтветСкрыть ответ
3, 7, 11; 10, 7, 4, 1; ни одного.
Как записать перебор чисел от 20 до 30 включительно? Сколько в нём чисел?
ОтветСкрыть ответ
range(20, 31); 11 чисел.
Перепиши цикл через for:
i = 0while i < 10: print(i) i += 2ОтветСкрыть ответ
for i in range(0, 10, 2): и в теле print(i): начало 0, граница 10, шаг 2.
Что выведет цикл for i in range(3), в теле которого сначала i = i * 10, а потом print(i)?
ОтветСкрыть ответ
0, 10 и 20: в начале каждой итерации i снова получает очередное число range.
Что напечатает программа поиска первого кратного 17, если перебирать range(103, 119)?
ОтветСкрыть ответ
None: между 103 и 118 кратных 17 нет (102 и 119 — за границами), и answer остался прежним.
Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Напиши программу: кратные 9 до 200
Напиши программу, которая находит количество и сумму чисел от 1 до 200 включительно, кратных 9, — циклом по range с шагом 9. Запусти её и запиши, что она напечатала.
Запишите два числа через пробел: количество, затем сумму.
Подсказка
Первое кратное 9 — само 9, шаг 9; граница — 201, чтобы 200 входило в перебор.
Разбор
Например:
count = 0total = 0for n in range(9, 201, 9): count += 1 total += nprint(count, total)Кратные 9 от 9 до 198: их 22, сумма 2277.
Ответ: 22 2277
Что напечатает программа?
count = 0for a in range(1, 6): for b in range(1, 6): if a < b: count += 1print(count)Введите число.
Подсказка
Для каждого a внутренний цикл перебирает все b; считаются пары, где a меньше b.
Разбор
При a = 1 подходят четыре b, при a = 2 — три, затем два, одно и ни одного: 4 + 3 + 2 + 1 = 10.
Ответ: 10
Напиши программу: первое кратное 23 от 500
Напиши программу, которая находит наименьшее число, не меньшее 500, которое делится на 23: перебор по возрастанию с break. Запусти её и запиши ответ.
Введите число.
Подсказка
Перебирай с 500 вверх и останови цикл break на первом числе с нулевым остатком от деления на 23.
Разбор
Например:
for n in range(500, 1000): if n % 23 == 0: print(n) break23 · 21 = 483 < 500, а 23 · 22 = 506.
Ответ: 506
Напиши программу: три наибольших подходящих числа
Напиши программу, которая находит три наибольших числа меньше 1000, которые делятся на 13 и оканчиваются цифрой 1. Перебирай вниз от 999 и останови цикл после третьего найденного. Запусти её и запиши ответ.
Запишите три числа через пробел в том порядке, в каком их найдёт перебор вниз.
Подсказка
range(999, 0, -1) идёт вниз. Оканчивается на 1 — n % 10 == 1. Счётчик найденных и break, когда он станет 3.
Разбор
Например:
found = 0for n in range(999, 0, -1): if n % 13 == 0 and n % 10 == 1: print(n, end=" ") found += 1 if found == 3: breakПеребор вниз встречает 871, 741 и 611.
Ответ: 871 741 611
Напиши программу: четырёхзначные числа с суммой цифр 10
Напиши программу, которая считает четырёхзначные числа с суммой цифр 10: перебери числа от 1000 до 9999 и для каждого найди сумму цифр циклом while из прошлого урока. Запусти её и запиши ответ.
Введите число.
Подсказка
Внешний for по range(1000, 10000); внутри — while по рабочей копии числа, чтобы не испортить переменную цикла.
Разбор
Например:
count = 0for number in range(1000, 10000): n = number digit_sum = 0 while n > 0: digit_sum += n % 10 n //= 10 if digit_sum == 10: count += 1print(count)Программа насчитывает 219 таких чисел.
Ответ: 219
Напиши программу: решения x + y + z = 10
Сколько решений у уравнения x + y + z = 10, если x, y и z — целые от 1 до 9? Напиши программу с тремя вложенными циклами, запусти её и запиши ответ.
Введите число.
Подсказка
Три цикла по range(1, 10); тройка считается, если сумма равна 10.
Разбор
Например:
count = 0for x in range(1, 10): for y in range(1, 10): for z in range(1, 10): if x + y + z == 10: count += 1print(count)Программа насчитывает 36 троек.
Ответ: 36