К содержанию

Модуль 3 · Урок 3.2

Цикл for и диапазоны

for перебирает готовый набор значений; range задаёт числа с исключённой правой границей.

6 задач

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

В примерах будем искать и считать кратные: первое кратное 17 среди чисел от 100 до 200, кратные 7 до 100.

Цикл for

for по очереди берёт значения источника и выполняет тело для каждого. Источник — то, из чего можно брать значения по одному, например строка или range:

for letter in "CODE":    print(letter)
C O D E

На каждой итерации имя 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=" ")
0 1 2 3 2 3 4 5 5 3 1

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 — схема и список значений пересчитываются сразу.

list(range(2, 9, 3)) → [2, 5, 8]

Переменная цикла

Присваивание переменной цикла не меняет следующие значения for.

for i in range(3):    print(i)    i = 100
0 1 2

Присваивание связывает имя i с 100 только до конца итерации. Следующая итерация снова берёт очередное число из range. Если правила перехода должны меняться по ходу, нужен while.

Вложенные циклы

Во вложенных циклах внутренний выполняется целиком для каждого значения внешнего. Так перебирают все пары: строки и столбцы таблицы, два числа из диапазона. Нажми «Запуск» и пройди по шагам:

for row in range(2):    for column in range(3):        print(row, column)
0 0 0 1 0 2 1 0 1 1 1 2

Для каждого 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)
102

Перебор идёт по возрастанию, поэтому первое найденное число — наименьшее, и дальше искать незачем. Запись 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)
14 735

То же можно перебрать сразу по кратным: 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)
4↵ 5↵ -2↵ 10↵ 7↵ 20 10

Первое число читаем до цикла — с него начинаются и сумма, и лучшее. Остальные 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)Повторить действие известное число раз.

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1

Какие числа дают range(3, 15, 4), range(10, 0, -3) и range(5, 5)?

ОтветСкрыть ответ
Ответ

3, 7, 11; 10, 7, 4, 1; ни одного.

Вопрос 2

Как записать перебор чисел от 20 до 30 включительно? Сколько в нём чисел?

ОтветСкрыть ответ
Ответ

range(20, 31); 11 чисел.

Вопрос 3

Перепиши цикл через for:

i = 0while i < 10:    print(i)    i += 2
ОтветСкрыть ответ
Ответ

for i in range(0, 10, 2): и в теле print(i): начало 0, граница 10, шаг 2.

Вопрос 4

Что выведет цикл for i in range(3), в теле которого сначала i = i * 10, а потом print(i)?

ОтветСкрыть ответ
Ответ

0, 10 и 20: в начале каждой итерации i снова получает очередное число range.

Вопрос 5

Что напечатает программа поиска первого кратного 17, если перебирать range(103, 119)?

ОтветСкрыть ответ
Ответ

None: между 103 и 118 кратных 17 нет (102 и 119 — за границами), и answer остался прежним.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Напиши программу: кратные 9 до 200

Напиши программу, которая находит количество и сумму чисел от 1 до 200 включительно, кратных 9, — циклом по range с шагом 9. Запусти её и запиши, что она напечатала.

Запишите два числа через пробел: количество, затем сумму.

Что напечатает программа?

count = 0for a in range(1, 6):    for b in range(1, 6):        if a < b:            count += 1print(count)

Введите число.

Напиши программу: первое кратное 23 от 500

Напиши программу, которая находит наименьшее число, не меньшее 500, которое делится на 23: перебор по возрастанию с break. Запусти её и запиши ответ.

Введите число.

Напиши программу: три наибольших подходящих числа

Напиши программу, которая находит три наибольших числа меньше 1000, которые делятся на 13 и оканчиваются цифрой 1. Перебирай вниз от 999 и останови цикл после третьего найденного. Запусти её и запиши ответ.

Запишите три числа через пробел в том порядке, в каком их найдёт перебор вниз.

Напиши программу: четырёхзначные числа с суммой цифр 10

Напиши программу, которая считает четырёхзначные числа с суммой цифр 10: перебери числа от 1000 до 9999 и для каждого найди сумму цифр циклом while из прошлого урока. Запусти её и запиши ответ.

Введите число.

Напиши программу: решения x + y + z = 10

Сколько решений у уравнения x + y + z = 10, если x, y и z — целые от 1 до 9? Напиши программу с тремя вложенными циклами, запусти её и запиши ответ.

Введите число.