$ sudo teach IT
Модуль 4 · Циклы · Урок 4.3

Цикл for и range()

Второй вид цикла в Python: перебираем числа и символы без ручного счётчика, а range() задаёт границы одной строкой.

Теория + практика~35 минутНовичок

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

В этом уроке разберём синтаксис for, функцию range() и перебор символов строки. while и for не конкурируют: while удобен, когда условие произвольное и заранее неизвестно, сколько будет повторений, а for — когда есть готовая последовательность или известно число шагов.

Главная идея урока: представьте, что вы раздаёте тетради каждому ученику по списку. Вы не считаете вручную «первый, второй, третий» и не проверяете каждый раз «список ещё не закончился?» — вы просто берёте следующего ученика по очереди, пока список не кончится. Цикл for работает точно так же: сам берёт следующий элемент, пока они не закончатся.

Синтаксис for: команда «пройди по каждому»

Простыми словами: вместо того чтобы объяснять Python, когда остановиться, вы даёте ему готовый набор значений и говорите «выполни тело цикла для каждого из них по очереди». Пока в наборе есть необработанные значения, цикл продолжается. Как только они кончились — цикл завершается сам, без всяких сравнений.

Официально это называется цикл for. Общий вид конструкции такой:

for переменная in последовательность:
    # тело цикла

Посмотрим на конкретный пример, где последовательностью выступает результат функции range() — о ней подробно поговорим в следующем разделе, а пока достаточно знать, что range(5) даёт числа от 0 до 4:

for i in range(5):
    print(i)

Разбираем построчно:

for — ключевое слово, с него начинается цикл, только строчными буквами.
i — переменная цикла. Вы придумываете ей имя сами, как обычной переменной. На каждом шаге Python сам кладёт в неё очередное значение — вручную ничего присваивать не нужно.
in — ключевое слово, соединяет переменную и последовательность. Читается как «в»: «i в range(5)».
range(5) — последовательность, по которой идёт перебор. Даёт числа 0, 1, 2, 3, 4.
двоеточие : — обязательный знак, тот же самый, что вы уже видели в if и while. Он открывает тело цикла.
print(i) — тело цикла, сдвинутое вправо на 4 пробела. Выполняется один раз на каждое значение i.

Python выполняет это так: берёт первое значение из range(5) (это 0), кладёт его в i, выполняет тело — печатает 0. Потом берёт следующее значение (1), снова выполняет тело — печатает 1. И так далее, пока значения не закончатся. На экране появится:

0
1
2
3
4

Обратите внимание: здесь нет ни счётчика, который вы заводите сами, ни условия остановки, ни строки, которая его увеличивает. Всё это Python делает за вас, отталкиваясь от того, что вы передали в range(5).

range(stop): числа от нуля до N минус один

Простыми словами: если сказать «дай мне пять чисел, начиная с нуля», получится 0, 1, 2, 3, 4 — ровно пять штук, но последнее число будет не 5, а 4. Это может показаться странным, но у такого правила есть практическая причина, разберём её чуть ниже.

Официально range(stop) — это вызов функции range с одним аргументом. Он возвращает последовательность целых чисел от 0 до stop минус 1 включительно, то есть само число stop в последовательность не входит.

for i in range(4):
    print(i)

# Вывод:
# 0
# 1
# 2
# 3
Почему не включает stop? Это сознательное решение авторов Python. range(4) возвращает ровно 4 числа — 0, 1, 2, 3, то есть столько же, сколько вы указали в скобках. Если бы stop включался, чисел получилось бы на одно больше, чем вы написали, и постоянно приходилось бы держать это в уме.

range(start, stop): задаём число, с которого начать

Простыми словами: иногда отсчёт нужен не с нуля, а, например, с 10 или с 1. Тогда вы просто говорите, с какого числа стартовать, и до какого (не включая его) идти.

Официально это второй вариант вызова — range(start, stop) с двумя аргументами. Последовательность идёт от start включительно до stop не включительно, с шагом 1.

for i in range(1, 6):
    print(i, end=" ")

# Вывод: 1 2 3 4 5

Разбор: start равен 1 — отсчёт начнётся с единицы. stop равен 6, но само число 6 в вывод не попадёт — ровно как и в range(stop), последняя граница не включается. end=" " вы уже знаете из работы с print() — заменяет перевод строки на пробел, поэтому числа печатаются в одну строку.

Правило простое: range(a, b) — это числа от a до b, но b не включается. Хотите, чтобы b тоже попало в перебор — пишите range(a, b + 1). Этот приём вы уже видели в задачах на while: он работает и здесь.

range(start, stop, step): шаг и обратный отсчёт

Простыми словами: если считать не подряд, а, скажем, через одно число — 0, 2, 4, 6 — нужно указать, насколько «прыгать» на каждом шаге. А если считать не вперёд, а назад — шаг должен быть отрицательным.

Официально третий аргумент range(start, stop, step) называется шагом: на сколько увеличивается (или уменьшается) число на каждой итерации. По умолчанию шаг равен 1, но можно указать любое целое число, кроме нуля.

for i in range(0, 11, 2):
    print(i, end=" ")
# Вывод: 0 2 4 6 8 10

for i in range(10, 0, -1):
    print(i, end=" ")
# Вывод: 10 9 8 7 6 5 4 3 2 1

В первом примере step равен 2 — числа идут через одно, поэтому нечётные пропускаются. Во втором примере step равен -1 — отрицательный шаг, поэтому последовательность идёт убывая: 10, потом 9, потом 8 и так далее. Обратите внимание: при отрицательном шаге start должен быть БОЛЬШЕ stop, иначе последовательность окажется пустой — ниже разберём это отдельно как частую ошибку.

Ловушка: шаг не может быть равен нулю. Если написать range(0, 10, 0), Python выбросит ошибку ValueError: range() arg 3 must not be zero — и это логично: с шагом 0 число никогда бы не изменилось, и перебор шёл бы вечно.

for по строке: перебираем символы один за другим

Простыми словами: строка — это не одно неделимое целое, а последовательность символов, выстроенных по порядку, как бусины на нитке. Если «пройтись» по строке циклом for, вы получите её буквы одну за другой, слева направо.

Официально строка, как и результат range(), является последовательностью — объектом, по которому for умеет перебирать элементы. Для строки элементом каждого шага становится один символ.

word = "код"

for char in word:
    print(char)

# Вывод:
# к
# о
# д

Разбор: word — обычная строковая переменная. char — переменная цикла, на каждом шаге в неё попадает очередной символ строки: сначала «к», потом «о», потом «д». Имя char выбрано для понятности (от английского «character» — символ), но подойдёт любое имя переменной.

Это особенно полезно в связке с if — например, чтобы посчитать, сколько раз в строке встречается конкретный символ:

text = "аббревиатура"
count = 0

for char in text:
    if char == "а":
        count += 1

print(f"Буква «а» встречается {count} раз")
# Буква «а» встречается 3 раз

Здесь count — знакомый вам аккумулятор: завели до цикла с нулём, и на каждом шаге, где символ совпал с "а", прибавили к нему 1. Устроено это ровно так же, как накопление суммы в цикле while — поменялся только способ перебора.

Совет: слово in из for char in text и оператор in из if char in vowels выглядят одинаково, но это разные вещи: в первом случае — часть синтаксиса цикла, во втором — проверка принадлежности. Не путайте их.

break и continue работают в for так же, как в while

Простыми словами: вы уже умеете досрочно прерывать цикл или пропускать одну итерацию в while. В for это работает по тем же правилам, ничего нового учить не нужно.

Официально break немедленно завершает цикл целиком, а continue прерывает только текущий шаг и переходит к следующему значению последовательности.

for i in range(1, 50):
    if i % 7 == 0:
        print(f"Первое число, кратное 7: {i}")
        break

Как только i станет равно 7 и условие i % 7 == 0 сработает впервые, программа напечатает найденное число и break сразу оборвёт цикл — оставшиеся значения от 8 до 49 даже не будут проверены.

Частые ошибки

Ошибка на единицу (off-by-one). Забыли, что stop не включается. Если нужны числа от 1 до 10 включительно, а вы написали range(1, 10) — получите только до 9. Правильно: range(1, 11).
Перепутали направление для обратного отсчёта. range(1, 10, -1) не выведет ничего: шаг отрицательный, а start меньше stop, поэтому последовательность сразу пустая. Для убывания нужно, чтобы start было больше stop: range(10, 1, -1).
Пытаются «перескочить» шаг цикла, меняя переменную вручную. В отличие от while, ручное изменение переменной цикла внутри тела for никак не влияет на порядок перебора — на следующем шаге Python всё равно возьмёт очередное значение из range() или строки, а не то, что вы туда записали.
for i in range(3):
    i = 100      # не поможет, i всё равно вернётся к 0, 1, 2
    print(i)
# Вывод: 100 100 100

Что важно запомнить

  • for переменная in последовательность: сам подставляет в переменную очередное значение и сам решает, когда остановиться — ручной счётчик и условие не нужны.
  • range(stop) — числа от 0 до stop − 1. Последнее число НЕ включается.
  • range(start, stop) — от start до stop − 1. Хотите включить stop — пишите stop + 1.
  • range(start, stop, step) — с шагом. Для обратного отсчёта шаг отрицательный, а start должен быть больше stop. Шаг не может быть нулём.
  • Строка — тоже последовательность: for char in text перебирает её символы по одному.
  • break и continue работают в for так же, как в while: break обрывает цикл, continue пропускает шаг.

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

5 вопросов

Подсчёт гласных в строке

Дана строка. Посчитай, сколько в ней гласных букв (а, е, ё, и, о, у, ы, э, ю, я, в любом регистре), с помощью цикла for.

text = "Программирование на Python — это увлекательно!"
vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ"

Результат сохрани в переменную count. Программа должна печатать: Гласных букв: 15

FizzBuzz

Напиши программу, которая выводит числа от 1 до 30. Но:

  • Если число кратно 3 — выведи Fizz
  • Если число кратно 5 — выведи Buzz
  • Если число кратно 15 (и 3, и 5 одновременно) — выведи FizzBuzz
  • Иначе — выведи само число

Используй цикл for и range(). Каждое значение — на отдельной строке.

Сумма чисел, кратных 3 или 5

Найди сумму всех чисел от 1 до N включительно, которые делятся без остатка на 3 или на 5. Используй цикл for и функцию range().

N = 50

Результат сохрани в переменную total. Программа должна печатать: Сумма чисел от 1 до 50, кратных 3 или 5: 593

Таблица умножения на n

Дано число n = 7. Напечатай таблицу умножения этого числа на числа от 1 до 10 циклом for и range(). Каждая строка — в формате 7 x 1 = 7. Должно получиться ровно 10 строк, от 7 x 1 = 7 до 7 x 10 = 70.

Факториал через for

Факториал числа n (записывается как n!) — это произведение всех целых чисел от 1 до n. Например, 4! = 1 × 2 × 3 × 4 = 24.

n = 6

Посчитай n! циклом for и сохрани результат в переменную result.