Цикл for и range
В прошлом уроке бегун с циклом while сам вёл счёт кругов. Табличку на старте ставили вручную, арку проверяли вручную, и счётчик кругов тоже отмечали сами. Стоит забыть n += 1, и цикл становится бесконечным.
Теперь представьте, что у дорожки стоит судья с готовым списком номеров кругов. Перед каждым кругом он вручает бегуну следующий номер. Когда номера в списке кончаются, бег окончен. Бегуну больше не нужно ничего считать: номер круга приходит сам.
Так работает цикл for: он берёт значения по очереди из готового ряда. Ряд целых чисел даёт функция range. Вот та же сумма от 1 до 100:
total = 0
for i in range(1, 101):
total += i
print(total) # 5050Давайте разберём программу по строкам:
total = 0готовит сумму.for i in range(1, 101):перед каждой итерацией записывает вiследующее число ряда.total += iприбавляет это число к сумме.print(total)выполняется после цикла и печатает5050.
Как работает for
Перед каждой итерацией for записывает в переменную i следующее число ряда: сначала 1, затем 2 и так далее. Тело выполняется для каждого значения. Когда значения кончаются, цикл заканчивается, и программа переходит к строке после него.
Увеличивать i в теле не нужно — следующее значение for возьмёт сам. Поэтому забыть счётчик, как в while, здесь не получится.
Объект, из которого for берёт значения по одному, называют итерируемым объектом. Функция range даёт такой объект, и строка — тоже такой объект. Цикл по строке перебирает её символы слева направо, и на каждой итерации ch — строка из одного символа:
for ch in "abc":
print(ch, end=".") # a.b.c.Здесь аналогия со списком судьи неточна. Судья держит в руках весь список, а range не хранит числа: он вычисляет следующее, когда for его просит. Поэтому range(1, 1000001) занимает в памяти столько же места, сколько range(1, 11).
Три формы range
Программа ниже показывает разные формы range. Разберём каждую.
for i in range(4):
print(i, end=" ") # 0 1 2 3
print()
for i in range(2, 10, 4):
print(i, end=" ") # 2 6
print()
for i in range(5, 0, -2):
print(i, end=" ") # 5 3 1Вызов print() без аргументов печатает только перевод строки, поэтому каждый ряд выходит на своей строке.
range(stop)
Форма с одним числом даёт числа от 0 до stop. Первый цикл, range(4), печатает 0 1 2 3: ряд начинается с нуля, а 4 в него не входит. Эту форму берут, когда нужно повторить действие ровно stop раз.
range(start, stop)
Форма с двумя числами даёт числа от start до stop. Так написан первый пример урока: range(1, 101) начинается с 1 и заканчивается на 100. Эту форму берут, когда счёт начинается не с нуля.
range(start, stop, step)
Третье число — шаг: каждое следующее число равно предыдущему плюс step. Во втором цикле range(2, 10, 4) даёт 2 и 6. После 6 шло бы 10, но это уже stop, и ряд на нём обрывается.
Отрицательный шаг ведёт ряд вниз: range(5, 0, -2) даёт 5, 3 и 1, а 0 снова не входит.
stop не входит в ряд
Во всех трёх формах stop в ряд не входит: ряд заканчивается раньше, чем дошёл бы до stop. Чтобы ряд включал последнее нужное число, stop берут на единицу больше него. Сумма до 100 поэтому записана как range(1, 101).
Это частый вопрос на собеседовании: сколько чисел даёт range(start, stop)? Если stop больше start, а шаг равен 1, ответ — stop - start.
Если start не меньше stop при положительном шаге, ряд пуст, и тело не выполнится ни разу. Например, range(5, 2) не даёт ни одного числа.
Частая ошибка
Число итераций посчитали делением /:
n = 10
for i in range(n / 2): # ✗
print(i)TypeError: 'float' object cannot be interpreted as an integerОператор / всегда даёт float, здесь это 5.0, а range принимает только целые числа. Деление нацело n // 2 даёт int 5, и цикл напечатает числа от 0 до 4.
Главное
forберёт значения по очереди из итерируемого объекта: изrange— числа, из строки — символы.- Счётчик в
forменять не нужно: следующее значение цикл берёт сам. range(start, stop, step)не включаетstop;startпо умолчанию0,step—1.rangeпринимает только целые числа: число итераций считают через//, а не/.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.