Кот-наставник— Привет! Я кот-наставник, провожу людей через Python на платформе SkillPy. И начну с главного секрета: программист ленив в хорошем смысле.
— Если действие нужно повторить сто раз, он не пишет сто строк — он пишет цикл.
— Здесь важно не выучить два ключевых слова, а понять, когда код возвращается назад и когда наконец выходит. Этим и займёмся.
Циклы в Python — это for и while: две конструкции, которые повторяют блок кода. Без них программа выполняется строго сверху вниз, а любое повторение приходится копировать руками. С циклами код обрабатывает список заказов, ждёт корректный ввод, считает сумму за месяц или рисует таблицу умножения — одним и тем же коротким блоком.
В этом гайде разберём оба цикла с нуля: синтаксис while, перебор через for, функцию range(), операторы break и continue, вложенные циклы, накопители и частые ошибки вроде зависшей программы. Все примеры запускаются в Python 3.12 без библиотек. Если пока путаются int, str и bool, сначала загляни в гайд Типы данных в Python: полный гайд для начинающих.
Зачем нужны циклы в Python
Допустим, нужно вывести приветствие три раза. Без цикла это выглядит так:
print("Привет")
print("Привет")
print("Привет")Привет Привет Привет
Работает, но проблем сразу три
- ❌ Код не масштабируется. Три строки скопировать легко, сто — уже нет.
- ❌ Правки дорогие. Изменить текст придётся в каждой строке отдельно.
- ❌ Легко ошибиться. Одна лишняя или пропущенная строка — и результат другой.
Цикл — конструкция, которая повторяет блок кода. Одно полное выполнение этого блока называется итерацией. В Python есть два цикла:
whileповторяет, пока истинно условие, аforперебирает элементы готовой последовательности.
Цикл while в Python: повторяй, пока условие истинно
Слово while переводится как «пока». Цикл проверяет условие перед каждой итерацией: если получается True — выполняет тело цикла, если False — выходит и продолжает программу дальше.
Тот же вывод приветствия, но через цикл:
count = 0
while count < 3:
print("Привет")
count += 1Привет Привет Привет
Переменная count — счётчик. Он начинается с нуля, проверяется в условии и увеличивается на каждой итерации. Когда count доходит до 3, условие 3 < 3 даёт False, и цикл заканчивается. Чтобы повторить приветствие сто раз, достаточно изменить одно число в условии.
Анатомия записи while
| Часть | Что означает |
|---|---|
| while | Начать цикл |
| count < 3 | Условие: даёт True или False |
| : | Открыть тело цикла |
| Четыре пробела | Показать, какие строки повторяются |
Три обязательных шага любого счётчика
- Заведи переменную до цикла — count = 0
- Проверь её в условии — while count < 3:
- Измени внутри цикла — count += 1
Счётчик может не только расти, но и уменьшаться:
countdown = 3
while countdown > 0:
print(countdown)
countdown -= 1
print("Пуск!")3 2 1 Пуск!
Последняя строка написана без отступа, поэтому она не входит в тело цикла и выполняется один раз — после выхода. Отступы в Python определяют, какой код относится к циклу, поэтому это часть синтаксиса, а не оформление.
Запись count += 1 — короткая форма от count = count + 1. Так же работают -=, *= и /=. В циклах эта форма встречается почти всегда: она короче и сразу читается как «увеличить на единицу».
Цикл for в Python: перебор готовой последовательности
Цикл for решает другую задачу. Ему не нужны счётчик и условие: он берёт готовую последовательность и по очереди достаёт из неё элементы. Список, строка, диапазон чисел — на каждой итерации переменная цикла хранит очередной элемент.
Перебор списка покупок:
fruits = ["яблоко", "банан", "апельсин"]
for fruit in fruits:
print("Беру:", fruit)Беру: яблоко Беру: банан Беру: апельсин
Анатомия записи for
| Часть | Что означает |
|---|---|
| for | Начать перебор |
| fruit | Переменная цикла: очередной элемент |
| in | Указать, что перебираем |
| fruits | Последовательность: список, строка, range() |
| : | Открыть тело цикла |
Имя переменной цикла выбираешь сам. Пиши по смыслу данных: fruit для фруктов, price для цен, letter для символов. Цикл сам знает, сколько элементов в последовательности, поэтому забыть про счётчик и получить бесконечное повторение здесь невозможно.
Строку for тоже перебирает — по символам:
for letter in "код":
print(letter)к о д
Один и тот же перебор списка двумя способами:
- Через
whileи индексы: — Нужны счётчик,len()и обращение по номеру.python tasks = [ "купить кофе", "написать код", "погулять" ] i = 0 while i < len(tasks): print(tasks[i]) i += 1 - Через
for: — Цикл сам достаёт элементы по очереди.python tasks = [ "купить кофе", "написать код", "погулять" ] for task in tasks: print(task)
Результат одинаковый, но во втором варианте нет ни счётчика, ни len(), ни обращения по индексу — а значит, негде и ошибиться. Подробнее об индексах и методах списков — в гайде Списки в Python: создание, методы и срезы.
Если внутри цикла нужен и номер элемента, и сам элемент, не заводи счётчик вручную — используй enumerate():
for i, task in enumerate(tasks, start=1):
...Переменная i будет считать позиции, а task хранить значение.
Функция range() в Python: числа для цикла for
Часто перебирать нужно не готовый список, а просто числа: от 1 до 10, все чётные до 100, обратный отсчёт. Создавать такой список руками не нужно — есть функция range(), которая выдаёт последовательность чисел по правилу.
Числа от 1 до 3:
for number in range(1, 4):
print(number)1 2 3
Три формы записи range()
| Запись | Какие числа даёт | Пояснение |
|---|---|---|
| range(5) | 0, 1, 2, 3, 4 | Старт с нуля, стоп до 5 |
| range(2, 6) | 2, 3, 4, 5 | Свой старт и стоп |
| range(1, 10, 3) | 1, 4, 7 | Третье число — шаг |
| range(3, 0, -1) | 3, 2, 1 | Отрицательный шаг: назад |
| range(0) | ничего | Пустой диапазон, цикл не войдёт |
Если значение шага не нужно, а нужно только количество повторений, переменную цикла принято называть подчёркиванием:
for _ in range(3):
print("Привет")Привет Привет Привет
Подчёркивание _ — обычная переменная, но по негласному соглашению оно означает «значение мне не нужно». Такая запись сразу говорит читателю: важно повторить три раза, а номер итерации в теле цикла не используется.
Диапазон легко превратить в список и посмотреть глазами:
print(list(range(0, 11, 2)))[0, 2, 4, 6, 8, 10]
Сам range() числа не хранит: он вычисляет очередное значение в момент запроса. Поэтому range(1, 1000000) не занимает память под миллион элементов, а list() рядом с ним нужен только для наглядности.
Цикл for или while: что выбрать
Оба цикла взаимозаменяемы: любой for можно переписать через while и наоборот. Разница в том, сколько усилий уйдёт на поддержку кода. Ориентир простой: если количество повторений известно заранее — берёшь for, если повторять нужно до события — while.
| Ситуация | Подходящий цикл |
|---|---|
| Известно точное число повторений | for + range() |
| Нужно пройти список, строку или другую коллекцию | for |
| Повторять, пока не наступит событие | while |
| Запрашивать ввод до корректного значения | while True + break |
| Считать, пока не достигнут порог | while |
| Обработать данные и собрать статистику | for |
Кот-наставник— Практика показывает: в реальном коде
forвстречается чаще. Данные почти всегда приходят коллекцией, а перебирать коллекцию вручную счётчиком — лишняя работа.—
whileдержи для случаев, где заранее не знаешь, сколько будет кругов: ввод пользователя, ожидание ответа, игровой цикл.
Операторы break и continue в Python: управление циклом
Иногда цикл нужно оборвать посреди работы или пропустить один неудачный элемент. Для этого есть два оператора. Оба работают и в for, и в while.
breakнемедленно останавливает цикл: оставшийся код итерации не выполняется, следующих итераций не будет, программа продолжается со строки после цикла.
Ищем первый крупный заказ и выходим, как только нашли:
prices = [120, 340, 90, 780, 210]
for price in prices:
if price > 500:
print("Нашли дорогой заказ:", price)
break
print("Проверили заказ на", price)Проверили заказ на 120 Проверили заказ на 340 Проверили заказ на 90 Нашли дорогой заказ: 780
Последний элемент 210 цикл даже не увидел: break сработал раньше. Это и есть смысл оператора — не тратить итерации после того, как ответ найден.
continueпропускает остаток текущей итерации и переходит к следующей. Цикл при этом продолжает работать.
Считаем сумму только плюсовых температур:
temperatures = [21, -5, 24, -2, 19]
total = 0
for value in temperatures:
if value < 0:
continue
total += value
print("Сумма плюсовых:", total)Сумма плюсовых: 64
Когда значение отрицательное, continue пропускает строку total += value и цикл сразу берёт следующий элемент. Такой приём называют фильтрацией: «плохие» данные отбрасываются, остальные обрабатываются.
Тот же цикл, но счётчик увеличивается первым:
number = 0
while number < 5:
number += 1
if number % 2 == 0:
continue
print(number)1 3 5
Бесконечный цикл с выходом: while True и break
Условие while True истинно всегда, поэтому такой цикл сам не остановится. Это не ошибка, а рабочий приём: цикл крутится, пока внутри не сработает break. Подходит, когда число повторений заранее неизвестно — например, программа ждёт команду.
Простое меню с командами:
while True:
command = input("Команда (старт/стоп): ")
if command == "старт":
print("Программа запущена")
elif command == "стоп":
print("Программа остановлена")
break
else:
print("Неизвестная команда")
print("Выход")Неизвестная команда Программа запущена Программа остановлена Выход
В цикле while True выход держится только на break. Проверяй, что до него реально можно добраться: если условие выхода никогда не выполнится, программа зависнет. Разбор ветвления внутри такого цикла — в гайде if, elif и else в Python: условия с примерами.
Блок else у циклов: сработал ли break
После for и while можно поставить else. Здесь это слово означает не «иначе», а «цикл дошёл до конца сам, без break». Типичное применение — поиск: break значит «нашёл», else значит «перебрал всё и не нашёл».
Проверим, есть ли у числа делители:
number = 9
for divisor in range(2, number):
if number % divisor == 0:
print(f"{number} делится на {divisor}")
break
else:
print(f"{number} — простое число")9 делится на 3
Делитель нашёлся на числе 3, сработал break — и блок else был пропущен. Если заменить number на 7, ни один делитель не подойдёт, цикл завершится сам, и программа напечатает 7 — простое число.
Когда выполняется else у цикла
- Цикл перебрал всё и закончился сам — else выполняется
- Внутри сработал break — else пропускается
- Цикл не сделал ни одной итерации — else выполняется
Два способа узнать, сработал ли break:
- Через
elseу цикла: — Короче на две строки, но опирается на редкое правило.python for divisor in range(2, number): if number % divisor == 0: break else: print("Делителей нет") - Через флаг: — Так пишет большинство разработчиков.
python has_divisor = False for divisor in range(2, number): if number % divisor == 0: has_divisor = True break if not has_divisor: print("Делителей нет")
Второй вариант длиннее, зато читается без знания редкого правила: переменная has_divisor прямо говорит, что произошло в цикле.
Конструкцию for-else многие считают неудачной: даже создатель Python признавал, что слово else здесь выбрано зря. В своём коде спокойно используй флаг, а знать for-else стоит для чтения чужого — иначе смысл легко понять наоборот.
Вложенные циклы в Python
Цикл можно поместить внутрь другого цикла. Тогда на каждой итерации внешнего цикла внутренний проходит целиком. Так строят таблицы, сетки и любые данные с двумя измерениями — строками и столбцами.
Фрагмент таблицы умножения 3 × 3:
for row in range(1, 4):
for col in range(1, 4):
print(f"{row} × {col} = {row * col}")
print("---")1 × 1 = 1 1 × 2 = 2 1 × 3 = 3 --- 2 × 1 = 2 2 × 2 = 4 2 × 3 = 6 --- 3 × 1 = 3 3 × 2 = 6 3 × 3 = 9 ---
Внешний цикл отвечает за строки, внутренний — за столбцы. print("---") стоит с отступом внешнего цикла, поэтому срабатывает один раз на строку и разделяет блоки.
Аналогия — стрелки часов. Минутная (внутренний цикл) делает полный круг из 60 шагов, и только тогда часовая (внешний цикл) сдвигается на одно деление.
Как меняются переменные в примере выше
| Шаг | row | col | Вывод |
|---|---|---|---|
| 1 | 1 | 1 | 1 × 1 = 1 |
| 2 | 1 | 2 | 1 × 2 = 2 |
| 3 | 1 | 3 | 1 × 3 = 3 |
| 4 | 2 | 1 | 2 × 1 = 2 |
| … | … | … | … |
| 9 | 3 | 3 | 3 × 3 = 9 |
Ещё одна деталь: break и continue действуют только на ближайший цикл. Чтобы выйти сразу из обоих, нужен флаг и проверка во внешнем цикле.
Ищем пару чисел с нужной суммой:
target = 7
found = False
for first in range(1, 6):
for second in range(1, 6):
if first + second == target:
print(f"Нашли: {first} + {second} = {target}")
found = True
break
if found:
breakНашли: 2 + 5 = 7
Первый break выходит из внутреннего цикла, а проверка if found: останавливает внешний. Без флага внешний цикл продолжил бы перебор и нашёл ещё несколько пар.
Счётчики и накопители: цикл собирает результат
Цикл редко нужен ради самого повторения. Обычно за один проход он собирает результат: сумму, количество, рекорд. Приём один и тот же: переменная-накопитель заводится до цикла, обновляется внутри и используется после.
Сумма всех цен:
prices = [120, 340, 90]
total = 0
for price in prices:
total += price
print("Итого:", total)Итого: 550
Типовые накопители и их начальные значения
| Задача | Старт цикла | Действие внутри цикла |
|---|---|---|
| Сумма | total = 0 | total += value |
| Количество | count = 0 | count += 1 |
| Количество с условием | count = 0 | if условие: count += 1 |
| Максимум | top = 0 | if value > top: top = value |
| Минимум | low = float('inf') | if value < low: low = value |
| Текстовый отчёт | report = "" | report += текст |
Начальное значение решает всё. Для минимума нельзя стартовать с нуля: реальные значения будут больше, и минимум навсегда останется нулём. Поэтому берут float('inf') — бесконечность, которая больше любого числа. Для максимума в данных с отрицательными числами по той же логике подходит float('-inf').
Несколько накопителей за один проход:
spending = [1200, 450, 3800, 900, 2100]
total = 0
big_purchases = 0
maximum = 0
for amount in spending:
total += amount
if amount > 1000:
big_purchases += 1
if amount > maximum:
maximum = amount
print(f"Всего потрачено: {total} руб.")
print(f"Крупных покупок: {big_purchases}")
print(f"Самая большая покупка: {maximum} руб.")
print(f"В среднем: {total / len(spending):.2f} руб.")Всего потрачено: 8450 руб. Крупных покупок: 3 Самая большая покупка: 3800 руб. В среднем: 1690.00 руб.
Один цикл, три накопителя, четыре строки отчёта. Данные прочитаны ровно один раз — так и обрабатывают статистику в реальных программах.
Практический пример: кассовый чек
Соберём всё вместе: while True для ввода без известного числа шагов, break для завершения, continue для отбраковки мусора и накопители для итогов.
total = 0
items = 0
while True:
entry = input("Цена товара (или 'стоп'): ")
if entry == "стоп":
break
if not entry.isdigit():
print("Нужно целое число")
continue
total += int(entry)
items += 1
print(f"Добавлено. Товаров: {items}, сумма: {total} руб.")
if items == 0:
print("Чек пустой")
else:
print(f"Итого {items} товаров на {total} руб.")
print(f"Средняя цена: {total / items:.2f} руб.")Добавлено. Товаров: 1, сумма: 250 руб. Нужно целое число Добавлено. Товаров: 2, сумма: 1450 руб. Итого 2 товаров на 1450 руб. Средняя цена: 725.00 руб.
Разбор программы
while Trueкрутит ввод, пока не придёт команда выходаbreakзавершает цикл по слову «стоп»continueотбрасывает нечисловой ввод, не прерывая работу- Накопители
totalиitemsсобирают сумму и количество - F-строка выводит среднюю цену с двумя знаками после точки — подробнее в гайде f-строки в Python: форматирование строк просто и читаемо
Частые ошибки в циклах Python
- ❌ Переменная условия не меняется. В
whileобязательно должно быть действие, которое рано или поздно сделает условие ложным. Без него — бесконечный цикл. - ❌
continueстоит выше изменения счётчика. Вwhileоператор перепрыгнет строкуcount += 1, и цикл зависнет. Меняй счётчик первым. - ❌ Ожидание, что
range(1, 10)дойдёт до 10. Правая граница не входит. Нужны числа до 10 включительно — пишиrange(1, 11). - ❌ Пропущено двоеточие или сломан отступ. После
while условиеиfor x in yвсегда идёт:, а тело цикла — с отступом в четыре пробела. Не смешивай табы и пробелы. - ❌ Список меняется во время перебора. Удаление элементов внутри
forсбивает порядок и приводит к пропускам. Перебирай копию (for item in items[:]) или собирай новый список. - ❌
breakво вложенном цикле считают выходом из обоих. Он останавливает только тот цикл, в котором написан. Для полного выхода нужен флаг. - ❌ Счётчик внутреннего цикла заведён снаружи внешнего. Во вложенном
whileон не сбросится, и со второго круга внутренний цикл просто не выполнится.
Забытое двоеточие Python замечает сразу:
count = 0
while count < 3
print(count)
count += 1SyntaxError: expected ':'Короткие ответы на вопросы про циклы Python
Чем цикл for отличается от while?
for перебирает готовую последовательность и заканчивается, когда элементы закончились. while проверяет условие перед каждой итерацией и работает, пока условие истинно. Отсюда практическое правило: известно число повторений — for, известно только событие выхода — while.
Как повторить действие ровно N раз?
Через for _ in range(N):. Функция range() выдаст ровно N чисел, а подчёркивание покажет, что значение в теле цикла не нужно. Вариант с while тоже работает, но требует счётчика и лишней строки.
Как выйти сразу из двух вложенных циклов?
В Python нет команды выхода сразу из нескольких циклов. Стандартный приём — флаг: во внутреннем цикле ставишь found = True и break, а после него проверяешь if found: break во внешнем. Второй вариант — вынести поиск в функцию и вернуть результат через return.
Что делать, если программа зависла в цикле?
Прервать выполнение сочетанием Ctrl + C и проверить две вещи: меняется ли переменная из условия и может ли условие стать ложным. Чаще всего забыто изменение счётчика или continue стоит раньше него. В редакторе SkillPy зависший код останавливает таймаут, так что перезапускать вкладку не нужно.
Главное про циклы:
whileповторяет, пока условие истинноУсловие проверяется перед каждой итерацией. Внутри цикла обязательно должно меняться то, что стоит в условии.
count = 0 while count < 3: print("Привет") count += 1forперебирает готовую последовательностьСчётчик не нужен: переменная цикла сама получает очередной элемент списка, строки или диапазона.
fruits = ["яблоко", "банан", "апельсин"] for fruit in fruits: print(fruit)range()создаёт числа для циклаПервое число входит в последовательность, последнее — нет. Третий аргумент задаёт шаг, в том числе отрицательный.
for number in range(1, 10, 3): print(number)breakостанавливает цикл,continueпропускает шагbreakвыходит из цикла целиком,continueбросает текущую итерацию и переходит к следующей. Оба работают только с ближайшим циклом.for price in [120, 340, 780]: if price > 500: print("Дорого:", price) break- Вложенные циклы умножают количество итераций
Внутренний цикл проходит полностью на каждой итерации внешнего. Три круга по три шага — девять проходов.
for row in range(1, 4): for col in range(1, 4): print(row * col)
Кот-наставник— Циклы становятся понятными не с чтения, а с прогона. Возьми кассовый чек из примера и добавь своё правило: скидку от трёх товаров или запрет цены выше 100 000.
— А потом сломай его специально: убери
count += 1, поставьcontinueвыше счётчика. Увидеть зависший цикл своими глазами полезнее, чем прочитать про него дважды.
Научи код повторяться — и проследи каждую итерацию!
На SkillPy циклы пишешь сам: счётчики, накопители, поиск с break, фильтрация через continue. AI-наставник читает твоё решение, показывает, где цикл зависнет, и объясняет причину, а не просто ставит «неверно».
