Бесконечный цикл while True в Python
Цикл, который сам не кончается, а останавливается по событию: меню, игра-угадайка, поток задач. while True плюс break — главный цикл интерфейсов и игр.
Редакция Питоники
Все циклы до сих пор знали, когда им кончаться: список кончился, счётчик дошёл до границы, условие стало ложным. Но у многих программ конца нет — есть событие: пользователь выбрал выход, игрок угадал число, сервер получил команду останова. Для таких программ цикл пишут наоборот: сначала бесконечный, выход — по событию через break. Разбираем while True — главный цикл интерфейсов и игр.
while True: бесконечный по построению
Запись while True честна до прямолинейности: условие цикла — истина без всяких проверок. Сам он крутиться будет вечно; вечность обрывает только break:
charge = 3
while True:
print('Заряд:', charge)
charge -= 1
if charge == 0:
print('Выключаюсь')
break
Заряд: 3 Заряд: 2 Заряд: 1 Выключаюсь
Проверка if charge == 0 стоит в теле и срабатывает по ходу итерации — вот кто решает, когда выйти. Выйти из while True иначе никак: break — единственная дверь. Ту же задачу решает и while charge > 0 — обычный while из пятого урока; разница в намерении: while True пишут, когда условие выхода узнаётся внутри цикла, по ходу дела, а не в заголовке.
Обработка потока задач
tasks = ['полить цветы', 'покормить кота', 'выйти']
while True:
if not tasks:
print('План пуст')
break
task = tasks.pop(0)
print('Делаю:', task)
Делаю: полить цветы Делаю: покормить кота Делаю: выйти План пуст
Список тает с начала: pop(0) достаёт первую задачу. Проверка if not tasks — первая строка тела: список пуст, пора выходить. Здесь условие выхода известно заранее, поэтому честнее заголовок while tasks: — но на практике проверка в теле чаще, потому что условий выхода бывает несколько.
Меню с командой выхода
commands = ['привет', 'погода', 'выход', 'анекдот']
while True:
if not commands:
break
command = commands.pop(0)
if command == 'выход':
print('До встречи!')
break
print('Вы ввели:', command)
Вы ввели: привет Вы ввели: погода До встречи!
Классика интерфейсов: программа ждёт команду и выполняет её, пока пользователь не попросит выход. В песочнице команды лежат в списке; в настоящей программе их отдаёт input(), и цикл не меняется ни строчкой:
while True:
command = input('Команда: ')
if command == 'выход':
print('До встречи!')
break
print('Вы ввели:', command)
Замените список на input — получите настоящее меню. Заметьте: команда анекдот не выполнилась — break сработал раньше. while True честен: выход есть выход, никакой досмотр после него не делается.
Игра-угадайка
secret = 7
guesses = [3, 9, 7]
tries = 0
while True:
if not guesses:
print('Попытки кончились')
break
guess = guesses.pop(0)
tries += 1
if guess == secret:
print('Угадал за', tries, 'попытки')
break
print(guess, '- не то')
3 - не то 9 - не то Угадал за 3 попытки
У игры два события-выхода: игрок угадал или попытки кончились. Оба узнаются только внутри цикла — поэтому заголовок и написан while True. Счётчик tries растёт на каждой попытке: аккумулятор, который здесь же и страховка — попытки не бесконечны.
Главный цикл программы
В настоящей программе while True стоит обычно не внутри, а вокруг всей работы: приём события, обработка, вывод — и снова приём. Выход из такого цикла означает завершение программы целиком, а не выход из одной задачи. Меню, чат-бот, игровой сервер, загрузчик файлов — у всех у них есть этот внешний слой.
Отсюда практическое правило: если программа может завершиться по событию, цикл while True пишется в самом верху, а тело разбивается на небольшие блоки с понятными именами. Иначе через полсотни строк перестаёшь понимать, к какому break относится тот, что стоит на экране.
- приём события: команды, сообщения, строки из очереди или файла;
- проверка, не пора ли выходить: очередь пуста, флаг остановки, достигнут потолок итераций;
- обработка события под try/except, чтобы одна плохая запись не обрывала всю работу;
- вывод результата и переход к следующему шагу.
В песочнице вместо живого ввода стоит список — так видно ту же структуру, но с предсказуемым результатом. Когда цикл обрастает проверками, счётчик и try/except перестают быть украшением: без них программа либо зависает, либо падает на первом же мусорном значении.
continue: пропуск итерации
У break есть родственник — continue. Он не заканчивает цикл, а бросает остаток текущей итерации: тело начинается заново со следующего шага. В бесконечном цикле continue полезен там, где часть шагов нужно проигнорировать, а само вращение продолжить.
log = ['запуск', '', 'ошибка', '', 'останов']
while True:
if not log:
print('Лог разобран')
break
line = log.pop(0)
if not line:
continue
print('Строка:', line)
Строка: запуск Строка: ошибка Строка: останов Лог разобран
Пустые строки пропущены, а цикл не прервался. Разница с break видна на последней строке: после continue программа всё равно дошла до проверки «лог разобран». Правило простое: continue — это «этот шаг не считаем», break — это «всё, выходим».
battery = 60
while True:
print('Разряд:', battery)
# battery -= 20 забыли — выхода не будет
Зависание изнутри выглядит скучно: печать повторяет одну и ту же строку бесконечно. Причина — ни break, ни изменение переменной: циклу попросту нечего делать на пути к выходу.
Страховка: лимит итераций
guesses = [3, 9, 5, 4]
attempt = 0
while True:
if attempt == 3:
print('Лимит попыток — выход')
break
guess = guesses[attempt]
attempt += 1
print('Попытка', attempt, ':', guess)
Попытка 1 : 3 Попытка 2 : 9 Попытка 3 : 5 Лимит попыток — выход
Профессиональная привычка — ограничивать любой бесконечный цикл сверху: if attempt == 3: break. Даже если нужное событие никогда не наступит, цикл кончится через три итерации. Лимит не заменяет логику — он её страхует: зависание превращается в управляемый выход.
Внешний while True и внутренний for
Смешивать два вида циклов в одной конструкции — обычное дело для настоящей программы: внешний while True крутит «шаг работы», внутренний for перебирает содержимое текущего шага. Разница в том, кто отвечает за выход: внешний цикл — за событие, внутренний — за перебор.
batches = [
['отчёт', 'письмо'],
['счёт', 'чек'],
]
while True:
if not batches:
print('Все пачки разобраны')
break
batch = batches.pop(0)
for item in batch:
print('Обрабатываю:', item)
Обрабатываю: отчёт Обрабатываю: письмо Обрабатываю: счёт Обрабатываю: чек Все пачки разобраны
Внутренний for отработал обе пачки до конца, а внешний цикл решил, что пора закрываться. Обратите внимание на выход: break во внутреннем for выкинул бы из перебора только одну пачку, а внешний while True продолжил бы крутиться — про двойной выход поговорим ниже.
Как отличить зависание от долгой работы
Программа на while True может и работать, и не работать — снаружи это выглядит одинаково: крутится и не печатает ничего. Различать приходится по месту: добавьте печать на каждой итерации и посмотрите, растёт ли что-то.
steps = 0
while True:
steps += 1
print('шаг', steps)
if steps == 3:
print('дошли до цели')
break
шаг 1 шаг 2 шаг 3 дошли до цели
Если номер шага растёт — цикл работает, просто работает долго. Если шаг застрял на одном и том же значении — тело не меняет состояние, и выхода не будет. Это дешёвый способ отличить «медленно» от «зависло», и он работает лучше, чем перечитывание кода.
break во вложенном цикле
for floor in [1, 2]:
for flat in [3, 4]:
if flat == 4:
print('Вышли на этаже', floor)
break
Вышли на этаже 1 Вышли на этаже 2
Печатается две строки: break внутри внутреннего цикла вывел только его — внешний продолжил ход по этажам. Вложенные циклы с while True требуют двойного выхода: два break, условие с флагом или вынос внутреннего цикла в отдельную проверку.
Двойной выход: флаг вместо двух break
Классическая задача — найти пару элементов в двух списках и сразу закончить оба перебора. Один break тут не справится, и наивный вариант с ним внутри двух циклов даёт ровно то, чего не хочется: внешний цикл продолжает работать.
left = ['a', 'b', 'c']
right = ['d', 'b', 'z']
found = False
for x in left:
for y in right:
if x == y:
print('Совпадение:', x)
found = True
break
if found:
break
print('Поиск закончен, найдено:', found)
Совпадение: b Поиск закончен, найдено: True
Флаг found — булева переменная, которая переживает внутренний цикл. Внутренний break выходит только из перебора right, а проверка if found во внешнем теле выходит уже из перебора left. Один флаг вместо двух break — стандартный приём, когда из вложенной конструкции нужно выйти целиком.
found = False
for x in left:
for y in right:
if x == y:
found = True
break
if found: # проверка здесь, а не внутри
break
Когда while True — лишний
Бесконечный цикл — не признак силы программы, а способ не знать заранее, сколько раз повторять. Если количество повторов известно, while True превращается в балласт: вы пишете break вручную там, где цикл for справился бы сам. Разница в цене — одна лишняя проверка на каждой итерации.
items = ['a', 'b', 'c']
done = []
while True:
if not items:
break
done.append(items.pop(0))
print(done)
items2 = ['a', 'b', 'c']
done2 = []
for item in items2:
done2.append(item)
print(done2)
['a', 'b', 'c'] ['a', 'b', 'c']
Результат одинаковый, и это лучший аргумент в пользу for: он не требует проверки «а не кончилось ли», потому что конец списка известен. Моя практика такая: while True оставляем там, где правда есть событие выхода — команда, ответ, файл, ввод. Всё остальное — for. Если в while True нет ни одного места, где цикл может остановиться по внешнему событию, почти наверняка это просто for, написанный неуверенно.
| while условие | while True + break | |
|---|---|---|
| Когда условие известно | до запуска: список, счётчик | по ходу: команда, событие |
| Читается | крутись, пока верно | крутись, пока не скажу стоп |
| Главный риск | условие не меняется — зависание | break недостижим — зависание |
| Где уместен | перебор данных | меню, игры, серверы, потоки |
Сначала предскажи ответ в голове — это главный навык программиста.
n = 0
while True:
n += 2
if n >= 5:
print('стоп', n)
break
words = ['а', 'б', 'в']
while True:
if not words:
print('пусто')
break
print(words.pop())
n = 3
while True:
print(n)
n -= 1
if n == 1:
break
1. Чем завершают цикл while True?
2. Что будет, если в while True нет ни одного break?
3. break стоит внутри внутреннего цикла вложенной конструкции. Что он обрывает?
4. Зачем в while True ставят счётчик-лимит попыток?
5. Как настоящее меню получает команды от пользователя?
6. Чем continue отличается от break?
7. Зачем при выходе из вложенного цикла нужен булев флаг?
8. По какому признаку на месте отличают зависший цикл от долго работающего?
Соберите обратный отсчёт на while True: заряд = 5; на каждой итерации печатайте Заряд: N и уменьшайте заряд на 1; когда заряд станет нулём — напечатайте Отключение и выйдите через break.
Зачем нужен бесконечный цикл, если он зависает?
Он не зависает, а ждёт событие: меню крутится, пока пользователь не введёт выход, сервер — пока не получит команду останова. Конец программы определяется событием, а не заголовком цикла, поэтому и пишут while True с break по условию внутри.
Как правильно выйти из while True?
Через break внутри тела: проверить условие выхода — команду, счётчик, флаг — и вызвать break. Правило безопасности: break должен существовать и быть достижимым; для надёжности добавляют лимит итераций.
Урок 6: breakЧем while True отличается от while 1 и от обычного while?
while 1 — то же самое, просто истина записана числом; читается хуже. Обычный while с условием применяется, когда условие выхода известно до запуска; while True — когда событие узнаётся внутри цикла по ходу итерации.
Как остановить бесконечный цикл, если он уже запущен?
Локально — Ctrl+C в терминале: Python прервёт программу с KeyboardInterrupt. В браузерной песочнице — перезагрузить страницу: вечный цикл подвешивает вкладку, поэтому в уроках все блоки завершаются сами.
Урок 5: цикл whileЧем continue отличается от break?
continue пропускает только текущую итерацию: остаток тела не выполняется, цикл продолжается со следующего шага. break прерывает цикл целиком. В бесконечном цикле continue полезен для пропуска ненужных шагов, break — единственный способ выйти.
Как выйти сразу из двух вложенных циклов?
Через булев флаг: внутренний цикл ставит found = True и делает break, а сразу под ним, на уровне тела внешнего цикла, стоит проверка if found: break. Один break прерывает только ближайший цикл — вложенность тут обманчива.
Когда while True лучше обычного цикла for?
Когда у цикла есть внешнее событие выхода, которое наступит неизвестно когда: команда пользователя, ответ сервера, ввод из файла. Если количество повторов известно заранее, for честнее: он сам знает про конец данных, и break вручную не нужен.
Понравился урок? Сошлитесь на него
«Для таких программ цикл пишут наоборот: сначала бесконечный, выход — по событию через break.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Циклы · Урок 5
Цикл while в Python: повторять, пока условие
while повторяет тело, пока условие верно: число шагов заранее неизвестно. Разбираем проверку условия, шаг к выходу и главный риск — бесконечный цикл.
Циклы · Урок 6
Оператор break в Python: выход из цикла
break выходит из цикла немедленно: нашли нужное — перебирать остальное незачем. Разбираем break в for и while, поиск первого совпадения и мёртвый код после выхода.
Циклы · Урок 8
Вложенные циклы в Python: цикл в цикле
Цикл внутри цикла: дни и дела, план зала кинотеатра, таблица умножения и пары «каждый с каждым» — как читается вложенность и во сколько раз она умножает число шагов.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
json · Урок 3
Типы JSON и Python: таблица соответствий
Шесть пар перевода между JSON и Python: object — dict, array — list, true — True, null — None. И два типа, которые формат не понимает вовсе.
true false json pythonjson число int float
Строки · Урок 14
Юникод: ord, chr и кодировки
Каждый символ — это число из таблицы Юникода. Учимся видеть строку глазами компьютера: ord и chr, байты через encode, и главная боль новичков — кракозябры из-за кодировок.
python символ в число
Циклы · Урок 9
else у циклов в Python: поиск без флагов
У циклов for и while есть собственный else: он срабатывает, если перебор дошёл до конца без break. Поиск «нашли или нет» — в один заход и без флагов.
python цикл elsewhile else python