Цикл for

Теория

Цикл for перебирает элементы чего-то перебираемого: символы строки, числа из диапазона, а дальше — элементы списков и словарей. На каждой итерации переменная цикла получает следующий элемент, и выполняется тело. Когда элементы кончились — цикл заканчивается сам: в отличие от while, его не нужно останавливать вручную, и бесконечным он не станет.

Для повторения «N раз» и перебора номеров используют range — диапазон целых чисел. Внутри for работают те же break и continue, что и в while. Частый приём — накопление: переменная заводится до цикла и обновляется на каждой итерации (сумма, счётчик, флаг).

Наглядно

Таблица 1. Варианты range и числа, которые он выдаёт. Конец диапазона не входит — как в срезах строк.

Вызов Числа Где пригодится
range(5) 0, 1, 2, 3, 4 повторить 5 раз
range(1, 6) 1, 2, 3, 4, 5 номера с единицы
range(1040, 1045) 1040 … 1044 диапазон номеров заказов
range(0, 10, 2) 0, 2, 4, 6, 8 шаг 2
range(5, 0, -1) 5, 4, 3, 2, 1 обратный отсчёт

Таблица 2. Когда выбирать for, а когда while.

Ситуация Цикл Пример
перебрать известный набор for каждый символ артикула, номера заказов из диапазона
повторить известное число раз for + range 3 платежа рассрочки
повторять, пока выполняется условие while повторять оплату до успеха, добавлять товары до бюджета

На практике

Задача: проверить артикул и промокод посимвольно, вывести номера заказов, рассчитать график рассрочки и разметить ячейки склада.

Шаг 1. Перебираем символы строки

Считаем цифры в артикуле — строка перебирается по символам:

python
sku = "KB-0142"
digits = 0
for ch in sku:
    if ch.isdigit():
        digits += 1
print(digits)

Результат:

вывод
4

ch по очереди становится "K", "B", "-", "0"… Метод isdigit() отвечает, состоит ли строка только из цифр. Счётчик digits заведён до цикла — иначе он обнулялся бы на каждой итерации.

Шаг 2. Перебираем числа через range

Выводим номера заказов с 1040 по 1043:

python
for order_id in range(1040, 1044):
    print(f"Заказ №{order_id}")

Результат:

вывод
Заказ №1040
Заказ №1041
Заказ №1042
Заказ №1043

Чтобы включить 1043, конец диапазона — 1044: range не включает конец.

Шаг 3. Накапливаем результат

График рассрочки: заказ на 4497 ₽ делится на 3 равных платежа, после каждого показываем, сколько выплачено:

python
total = 4497
months = 3
payment = total // months
paid = 0
for month in range(1, months + 1):
    paid += payment
    print(f"Месяц {month}: платёж {payment} ₽, выплачено {paid} ₽")

Результат:

вывод
Месяц 1: платёж 1499 ₽, выплачено 1499 ₽
Месяц 2: платёж 1499 ₽, выплачено 2998 ₽
Месяц 3: платёж 1499 ₽, выплачено 4497 ₽

Шаг 4. Выходим раньше через break

Промокод допустим, если в нём только буквы и цифры — это проверяет метод isalnum(). Как только встретили недопустимый символ — дальше проверять нет смысла:

python
code = "SALE-10"
is_valid = True
for ch in code:
    if not ch.isalnum():
        is_valid = False
        break
print(is_valid)

Результат:

вывод
False

Флаг is_valid начинается с True и меняется только при нарушении. Цикл не должен переписывать его на каждой итерации — иначе результат зависел бы только от последнего символа.

Шаг 5. Вкладываем циклы

Разметка склада: на каждом из 2 стеллажей по 3 ячейки. Внутренний цикл проходит целиком для каждой итерации внешнего:

python
for shelf in range(1, 3):
    row = ""
    for cell in range(1, 4):
        row += f"{shelf}-{cell} "
    print(row.strip())

Результат:

вывод
1-1 1-2 1-3
2-1 2-2 2-3

Всего 2 × 3 = 6 итераций внутреннего тела. Вложенные циклы быстро умножают работу — на больших данных это первое место, где ищут тормоза.

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

  • Конец range. range(1040, 1043) не включает 1043. Нужен «по N включительно» — пишите range(a, N + 1).
  • Накопитель внутри цикла. total = 0 внутри тела обнуляет сумму на каждой итерации — в конце останется только последнее значение.
  • Флаг переписывается на каждой итерации. if ok: flag = True else: flag = False в цикле — результат зависит только от последнего элемента. Начальное значение — до цикла, внутри — только изменение при «нарушении».
  • Изменение переменной цикла. order_id += 1 внутри for не пропускает следующий элемент — на следующей итерации for всё равно присвоит очередное значение. Для пропуска — continue.
  • while со счётчиком вместо for. Ручной счётчик — лишний шанс ошибиться на единицу или зациклиться; для известного числа повторов — for и range.

Итог

Как работает for

  • for x in что-то: — x по очереди принимает каждый элемент; цикл заканчивается сам.
  • Строка перебирается по символам; дальше так же перебираются списки и словари.

range

  • range(n) — 0…n-1; range(a, b) — a…b-1; range(a, b, шаг), шаг может быть отрицательным.
  • Конец не входит: «по N включительно» — range(a, N + 1).

Приёмы

  • Накопление: переменная — до цикла, обновление — в теле.
  • Флаг: начальное значение до цикла, внутри — изменение и break.
  • break и continue работают так же, как в while.
  • Вложенные циклы: внутренний проходит полностью на каждой итерации внешнего.

Вопросы на собеседовании

Почему range(1, 10) не включает 10?

Полуоткрытые интервалы [начало, конец) — общее правило Python (так же работают срезы). Длина диапазона равна конец - начало, а соседние диапазоны range(0, 5) и range(5, 10) стыкуются без пересечений и пропусков.

Можно ли пропустить элемент, изменив переменную цикла for внутри тела?

Нет. На каждой итерации for сам присваивает переменной следующий элемент, поэтому изменение внутри тела действует только до конца текущей итерации. Пропустить элемент можно через continue.

Сколько памяти занимает range(1_000_000)?

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

Глубже

Что на самом деле делает for — протокол итерации, iter() и next() — в курсе «Python под капотом», тема «Как работает for».

Ошибка в тексте

Сообщить об ошибке могут зарегистрированные пользователи — так в сообщениях меньше спама.

Войти, чтобы сообщить