Циклы в программировании. Цикл while
Циклы являются такой же важной частью структурного программирования, как условные операторы. С помощью циклов можно организовать повторение выполнения участков кода. Потребность в этом возникает довольно часто. Например, пользователь последовательно вводит числа, и каждое из них требуется добавлять к общей сумме. Или нужно вывести на экран квадраты ряда натуральных чисел и тому подобные задачи.
Цикл while
«While» переводится с английского как «пока». Но не в смысле «до свидания», а в смысле «пока имеем это, делаем то».
Можно сказать, while является универсальным циклом. Он присутствует во всех языках, поддерживающих структурное программирование, в том числе в Python. Его синтаксис обобщенно для всех языков можно выразить так:
while логическое_выражение
Это похоже на условный оператор if . Однако в случае циклических операторов их тела могут выполняться далеко не один раз. В случае if , если логическое выражение в заголовке возвращает истину, то тело выполняется единожды. После этого поток выполнения программы возвращается в основную ветку и выполняет следующие выражения, расположенные ниже всей конструкции условного оператора.
В случае while , после того как его тело выполнено, поток возвращается к заголовку цикла и снова проверяет условие. Если логическое выражение возвращает истину, то тело снова выполняется. Потом снова возвращаемся к заголовку и так далее.
Цикл завершает свою работу только тогда, когда логическое выражение в заголовке возвращает ложь, то есть условие выполнения цикла больше не соблюдается. После этого поток выполнения перемещается к выражениям, расположенным ниже всего цикла. Говорят, «происходит выход из цикла».
Рассмотрите блок-схему цикла while .

На ней ярко-голубыми прямоугольниками обозначена основная ветка программы, ромбом – заголовок цикла с логическим выражением, бирюзовым прямоугольником – тело цикла.
С циклом while возможны две исключительные ситуации:
- Если при первом заходе в цикл логическое выражение возвращает False , то тело цикла не выполняется ни разу. Эту ситуацию можно считать нормальной, так как при определенных условиях логика программы может предполагать отсутствие необходимости в выполнении выражений тела цикла.
- Если логическое выражение в заголовке while никогда не возвращает False , а всегда остается равным True , то цикл никогда не завершится, если только в его теле нет оператора принудительного выхода из цикла ( break ) или вызовов функций выхода из программы – quit() , exit() в случае Python. Если цикл повторяется и повторяется бесконечное количество раз, то в программе происходит зацикливание. В это время она зависает и самостоятельно завершиться не может.
Вспомним наш пример из урока про исключения. Пользователь должен ввести целое число. Поскольку функция input() возвращает строку, то программный код должен преобразовать введенное к целочисленному типу с помощью функции int() . Однако, если были введены символы, не являющиеся цифрами, то возникает исключение ValueError , которое обрабатывается веткой except . На этом программа завершается.
Другими словами, если бы программа предполагала дальнейшие действия с числом (например, проверку на четность), а она его не получила, то единственное, что программа могла сделать, это закончить свою работу досрочно.
Но ведь можно просить и просить пользователя корректно вести число, пока он его не введет. Вот как может выглядеть реализующий это код:
n = input("Введите целое число: ") while type(n) != int: try: n = int(n) except ValueError: print("Неправильно ввели!") n = input("Введите целое число: ") if n % 2 == 0: print("Четное") else: print("Нечетное")
Примечание 1. Не забываем, в языке программирования Python в конце заголовков сложных инструкций ставится двоеточие.
Примечание 2. В выражении type(n) != int с помощью функции type() проверяется тип переменной n . Если он не равен int , то есть значение n не является целым числом, а является в данном случае строкой, то выражение возвращает истину. Если же тип n равен int , то данное логическое выражение возвращает ложь.
Примечание 3. Оператор % в языке Python используется для нахождения остатка от деления. Так, если число четное, то оно без остатка делится на 2, то есть остаток будет равен нулю. Если число нечетное, то остаток будет равен единице.
Проследим алгоритм выполнения этого кода. Пользователь вводит данные, они имеют строковый тип и присваиваются переменной n . В заголовке while проверяется тип n . При первом входе в цикл тип n всегда строковый, то есть он не равен int . Следовательно, логическое выражение возвращает истину, что позволяет зайти в тело цикла.
Здесь в ветке try совершается попытка преобразования строки к целочисленному типу. Если она была удачной, то ветка except пропускается, и поток выполнения снова возвращается к заголовку while .
Теперь n связана с целым числом, следовательно, ее тип int , который не может быть не равен int . Он ему равен. Таким образом логическое выражение type(n) != int возвращает False , и весь цикл завершает свою работу. Далее поток выполнения переходит к оператору if-else, находящемуся в основной ветке программы. Здесь могло бы находиться что угодно, не обязательно условный оператор.
Вернемся назад. Если в теле try попытка преобразования к числу была неудачной, и было выброшено исключение ValueError , то поток выполнения программы отправляется в ветку except и выполняет находящиеся здесь выражения, последнее из которых просит пользователя снова ввести данные. Переменная n теперь имеет новое значение.
После завершения except снова проверяется логическое выражение в заголовке цикла. Оно даст True , так как значение n по-прежнему строка.
Выход из цикла возможен только тогда, когда значение n будет успешно конвертировано в число.
Рассмотрим следующий пример:
total = 100 i = 0 while i 5: n = int(input()) total = total - n i = i + 1 print("Осталось", total)
Сколько раз «прокрутится» цикл в этой программе, то есть сколько итераций он сделает? Ответ: 5.
- Сначала переменная i равна 0. В заголовке цикла проверяется условие i < 5 , и оно истинно. Тело цикла выполняется. В нем меняется значение i , путем добавления к нему единицы.
- Теперь переменная i равна 1. Это меньше пяти, и тело цикла выполняется второй раз. В нем i меняется, ее новое значение 2.
- Два меньше пяти. Тело цикла выполняется третий раз. Значение i становится равным трем.
- Три меньше пяти. На этой итерации i присваивается 4.
- Четыре по прежнему меньше пяти. К i добавляется единица, и теперь ее значение равно пяти.
«Смысловая нагрузка» данного цикла – это последовательное вычитание из переменной total вводимых чисел. Переменная i в данном случае играет только роль счетчика итераций цикла. В других языках программирования для таких случаев предусмотрен цикл for , который так и называется: «цикл со счетчиком». Его преимущество заключается в том, что в теле цикла не надо изменять переменную-счетчик, ее значение меняется автоматически в заголовке for .
В языке Python тоже есть цикл for . Но это не цикл со счетчиком. В Питоне он предназначен для перебора элементов последовательностей и других сложных объектов. Данный цикл и последовательности будут изучены в последующих уроках.
Для while наличие счетчика не обязательно. Представим, что надо вводить числа, пока переменная total больше нуля. Тогда код будет выглядеть так:
total = 100 while total > 0: n = int(input()) total = total - n print("Ресурс исчерпан")
Сколько раз здесь выполнится цикл? Неизвестно, все зависит от вводимых значений. Поэтому у цикла со счетчиком известно количество итераций, а у цикла без счетчика – нет.
Самое главное для цикла while – чтобы в его теле происходили изменения значений переменных, которые проверяются в его заголовке, и чтобы хоть когда-нибудь наступил случай, когда логическое выражение в заголовке возвращает False . Иначе произойдет зацикливание.
Примечание 1. Не обязательно в выражениях total = total — n и i = i + 1 повторять одну и ту же переменную. В Python допустим сокращенный способ записи подобных выражений: total -= n и i += 1 .
Примечание 2. При использовании счетчика он не обязательно должен увеличиваться на единицу, а может изменяться в любую сторону на любое значение. Например, если надо вывести числа кратные пяти от 100 до 0, то изменение счетчика будет таким i = i — 5 , или i -= 5 .
Примечание 3. Для счетчика не обязательно использовать переменную с идентификатором i . Можно назвать переменную-счетчик как угодно. Однако так принято в программировании, что счетчики обозначают именами i и j (иногда одновременно требуются два счетчика).
Практическая работа
- Измените последний код из урока так, чтобы переменная total не могла уйти в минус. Например, после предыдущих вычитаний ее значение стало равным 25. Пользователь вводит число 30. Однако программа не выполняет вычитание, а выводит сообщение о недопустимости операции, после чего осуществляет выход из цикла.
- Используя цикл while , выведите на экран для числа 2 его степени от 0 до 20. Возведение в степень в Python обозначается как ** . Фрагмент вывода:
. 32 64 128 256 512 1024 .
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
1. Циклы с предусловием и постусловием
![]()
В условие описывается логическое выражение, истинность которого обеспечивает дальнейшую работу цикла. С помощью операторов записывается тело цикла.
Цикл выполняется до тех пор, пока выполняется условие, как только условие стало ложным цикл заканчивается.
Напишем программу, которая будет выводить на экран первые \(10\) целых чисел на экран.

Цикл с заданным условием окончания работы (цикл с постусловием) записывается с помощью оператора « repeat ».
Программирование в «Эврике»
В цикле с условием while цикл выполняется, пока истинно задающее его условие. Поэтому этот цикл также иногда называют циклом «пока». Часто цикл while используется, когда невозможно заранее предсказать, сколько раз необходимо выполнить тело цикла. В повседневной жизни цикл while можно встретить в алгоритмах, вроде «Пока в пределах видимости есть машины, стоять на месте» или «Пока в ящике есть детали, достать деталь из ящика».
В следующей программе цикл while используется подобно циклу for для вывода на экран всех чисел от 1 до 10:
i=1 while iВ этой программе переменной i присваивается значение 1. Затем начинается цикл (ключевое слово while ) с проверяемым условием i
Как только проверяемое условие станет ложно (это произойдет, когда переменная i станет равна 11), цикл завершит работу и управление будет передано следующей инструкции после блока цикла. Поэтому после завершения цикла переменная i будет иметь значение 11.
В общем виде синтаксис цикла с условием в языке Питон такой:
while условие: инструкция 1 инструкция 2 . инструкция n
- Условие, определяющее, будет ли выполняться тело цикла. Это условие записывается после слова while и может быть произвольным арифметическим выражением, в котором должен быть хотя бы один из операторов == , != , < , >, = и могут использоваться логические операторы and , or , not . После условия ставится двоеточие.
- Тело цикла, состоящее из одной или нескольких инструкций, записанных с отступом одинаковой величины.
- Инструкции, изменяющие значения переменных, входящих в проверяемое условие. В рассмотренном примере это инструкция i=i+1 . Если бы этой инструкции не было, то значение переменной i не менялось бы и проверяемое условие всегда было бы истинным, что привело бы к бесконечному циклу. Для прерывания работы программы, попавшей в бесконечный цикл, используется комбинация клавиш Ctrl+C .
n=input("Введите натуральное число") i=0 while 2**iВ этом примере переменная i внутри цикла увеличивается на 1, пока значение 2**i не превосходит n . После окончания цикла величина 2**i будет больше n , и соответствующее значение i будет напечатано на экране. Внутри цикла могут быть различные другие инструкции, в том числе инструкции if , while и for . В этом случае говорят о вложенных циклах, или об условной инструкции, вложенной в цикл. Тело вложенного цикла выделяется от цикла, в который оно вложено, большей величиной отступа. Рассмотрим два примера. В первом примере программа печатает на экран все натуральные делители данного натурального числа n . Для этого используется цикл, в котором переменная i меняется от 1 до n , а внутри цикла проверяется условие, и если остаток от деления n на i равен 0, то печатается значение i :
n=input("Введите число, для которого необходимо вывести делители") i=1 while iВ следующем примере на экран печатается таблица умножения всех однозначных чисел. Для этого организовано два цикла: в одном переменная i меняется от 1 до 9, внутри этого цикла (то есть при каждом новом значении i ) переменная j также меняется от 1 до 9. В блоке вложенного цикла на экран печатаются значения переменных i , j и их произведение:
i=1 while i for i in range(1,10): for j in range(1,10): print i, "*", j, " heading">Инструкции управления цикломВ циклах
whileиforможно использовать две инструкции, управляющие циклом.Инструкция
breakпрерывает выполнение цикла. Управление передается на следующую инструкцию после тела цикла.Инструкция
continueпрерывает текущую итерацию цикла. Все инструкции после инструкцииcontinueдо конца блока цикла пропускаются. В циклеforпеременной, которая меняется в цикле, присваивается следующее значение из списка и цикл продолжает выполняться с новым значением переменной. В циклеwhileпроверяется условие, заданное в цикле и если оно истинно, то цикл продолжает выполняться с начала блока цикла.Например, допустим, что нам необходимо перебрать в цикле все натуральные числа, меньшие
nи не делящиеся на 3. Для этого можно перебрать все числа, проверить их остаток от деления на 3, и если число делится на 3, выполнить инструкциюcontinue, которая пропустит оставшиеся до конца цикла инструкции и перейдет к следующему числу:for in range(n): if i%3==0: continue print i # а далее выполняем прочие необходимые действияИнструкции break и continue следует использовать только внутри условных инструкций. Безусловные инструкции break и continue , как правило, бессмысленны. Также в циклах while и for можно указать else -блок после основного блока цикла. else -блок в циклах выполняется один раз после завершения работы цикла, но только в случае, если цикл не был прерван инструкцией break . Поясним это на программе, которая по введенному целому числу n>1 определяет, является ли оно простым или составным.
n=input("Введите целое число, больше 1 ") # 1 Считали число n for d in range(2, n): # 2 d меняется от 2 до n-1 if n % d == 0: # 3 Проверка: n делится на d? print n, "имеет делитель", d # 4 break # 5 Завершаем цикл for else: # 6 Это else-блок цикла print n, "простое число" # 7Поясним эту программу. После ввода с клавиатуры числа n в программе организовывается цикл по переменной d , принимающей значения от 2 до n-1 (строка 2). Далее в теле цикла проверяется, является ли d делителем n (строка 3). Если является делителем, то на экран выводится соответствующее сообщение (строка 4) и при помощи инструкции break завершается выполнение цикла (строка 5). После тела цикла for идет else -блок. То, что инструкция else (строка 6) относится к циклу for (строка 2), а не к инструкции if (строка 3), определяется по величине отступа перед инструкцией else : отступ перед ней такой же, как и перед инструкцией for . Поэтому если цикл не был прерван инструкцией break , то есть для числа n не будет найден нетривиальный делитель, то будет выполнен else -блок, то есть на экран будет напечатано сообщение о том, что n — простое число (строка 7).
Какое слово команда обозначает данный цикл
При работе с циклами есть две полезных команды — break и continue. Здесь я опишу, что они делают и как их использовать.
Понятие тела цикла и итерации
Сначала введу несколько терминов, которые полезны при обсуждении циклов.
Тело цикла — это собственно те команды, которые находятся внутри цикла. Например, в цикле
for i:=1 to n do begin a:=i*i; writeln(i,' ',a); end;тело цикла состоит из двух команд: присваивания и вывода.
Итерацией называется каждый отдельный проход по телу цикла. Цикл всегда повторяет команды из тела цикла несколько раз — вот каждое такое повторение и называется итерацией. В примере выше можно сказать, что цикл сделает n итераций. Можно, например, сказать, что на пятой итерации цикла будет выведена строка "5 25".
Команда break
Команда break обозначает прервать выполнение цикла, и идти дальше выполнять те команды, которые идут после цикла. Т.е. если вы в некоторый момент решили, что больше вам циклиться не надо, и цикл уже отработал все, что надо, и вам нужно переходить к тому, что написано после цикла, то пишите break. Если это произошло посреди итерации, то итерация будет прервана — тело цикла до конца выполнено не будет.
for i:=2 to n do begin if n mod i=0 then begin writeln(i); break; end; writeln('Попробовали ',i,', не подходит'); end; writeln('Конец!');— как только условие if'а выполнится, на экран будет выведено соответствующее i, и выполнение цикла будет прервано — дальше будет выведено слово "Конец!" и т.д. При этом строка "Попробовали. " будет выводиться для всех i, не включая то, на котором выполнилось условие цикла.
Например, для n=9 вывод будет следующий:
Попробовали 2, не подходит 3 Конец!(Правда, данный конкретный код было бы проще написать через while — подумайте, как)
Команду break можно также применять и с циклами while и repeat, один из примеров — ниже.
Команда continue
Команда continue обозначает прервать выполнение текущей итерации цикла и начать следующую итерацию. Т.е. как будто бы, не доделывая то, что написано ниже в теле цикла, прыгнуть на начало цикла, при этом выполнив все действия, которые должны быть выполнены после очередной итерации — т.е. в цикле for увеличив значение счетчика цикла на 1, а в циклах while/repeat проверив условие и, если оно не выполняется, то вообще прервав работу.
for i:=2 to n-1 do begin if n mod i<>0 then begin writeln('Попробовали ',i,', не подходит'); continue; end; writeln(n,' делится на ',i); end;— здесь цикл пройдется по всем числам от 2 до n-1 и для каждого выведет, делится ли n на i или нет. Например, при n=9 вывод будет такой:
Попробовали 2, не подходит 9 делится на 3 Попробовали 4, не подходит . Попробовали 8, не подходитПройдем подробнее по началу выполнения этого кода. Сначала i становится равным 2. Смотрим: 9 mod 2<>0 --- значит, идем внутрь if. Выводим на экран "Попробовали. ", и далее идет команда continue. Значит, сразу идем на следующую итерацию: увеличиваем i (!), оно становится равным 3, и идем на начало цикла. 9 mod 3=0, поэтому в if не идем, выводим "9 делится на 3", итерация закончилась — увеличиваем i и идем на следующую итерацию. И так далее.
Конечно, в этом примере можно было бы обойтись и без continue, просто написать else. Это было бы проще. Но бывает, что вам надо перебрать числа, и есть много случаев, когда какое-то число вам не надо рассматривать. Тогда писать кучу else было бы намного сложнее, чем несколько continue. Например (пример выдуман из головы, но подобные случаи бывают):
for i:=1 to n do begin // нам не нужны числа, делящиеся на 5 if i mod 5=0 then continue; // нам не нужны числа, квадрат которых дает остаток 4 при делении на 7 // обратите внимание, что мы можем делать какие-то действия до проверки условий p:=i*i; if p mod 7=4 then continue; // все оставшиеся числа нам нужны, // поэтому здесь делаем какую-нибудь сложную обработку из многих команд . end;— тут намного более понятно, что вы имели в виду, чем если бы вы писали с else. С else тому, кто будет читать ваш код, пришлось бы смотреть, где else заканчивается, и вдруг после конца else идут еще какие-нибудь команды, а здесь все понятно: если if выполняется, то пропускается все оставшееся тело цикла.
while true do и break
Один важный случай применения команды break состоит в следующем. Часто бывает так, что вам надо повторять какую-то последовательность действий, и проверять условие окончания вам хочется в середине этой последовательности. Например, вам надо считывать с клавиатуры числа, пока не будет введен ноль. Все числа, кроме нуля, надо как-то обрабатывать (для простоты будем считать, что выводить на экран — это нам не существенно).
Естественная последовательность действий следующая:
считать число если ноль, то прерваться вывести это число на экран считать число если ноль, то прерваться вывести это число на экран .Очень четко видна цикличность, но если вы попытаетесь написать цикл без команды break, ничего хорошего у вас не получится.
У вас будет несколько вариантов: например, так
read(a); while a<>0 do begin writeln(a); read(a); end;Фактически вы "разрезали" циклическую последовательность действий на проверке условия окончания цикла, и в результате были вынуждены команду считывания числа задублировать: она у вас один раз перед циклом, и один раз в конце цикла. Дублирование кода — это не очень хорошо (если вам придется его менять, вы можете забыть, что один и тот же код в двух местах); если у вас вместо считывания числа будет чуть более сложный код, то будет еще хуже. Кроме того, в этой реализации не очень хорошо, что у вас в пределах одной итерации цикла есть разные значения переменной a, было бы проще, если бы каждая итерация цикла соответствовала работе только с одним введенным числом.
Второй вариант, который вам может придти в голову, такой:
a:=1; while a<>0 do begin read(a); if a<>0 then writeln(a); end;Этот вариант лучше в том смысле, что каждая итерация работает только с одним числом, но у него все равно есть недостатки. Во-первых, есть искуственная команда a:=1 перед циклом. Во-вторых, условие a<>0 дублируется; если вам придется его менять, вы можете забыть, что оно написано в двух местах. В-третьих, у вас основная ветка выполнения цикла, ветка, по которой будет выполняться большинство итераций, попала в if. Это не очень удобно с точки зрения кода: все-таки все числа, кроме последнего, будут не нулевыми, поэтому хотелось бы написать такой код, в котором обработка случая a=0 не потребует заворачивания основного варианта в if — так просто читать удобнее (особенно если бы у нас было бы не просто writeln(a), а существенно более сложный код обработки очередного числа, сам включающий несколько if'ов и т.п.).
Но можно сделать следующим образом:
while 0=0 do begin read(a); if a=0 then break; writeln(a); end;Искуственная констракция 0=0 — это условие, которое всегда верно: нам надо, чтобы while выполнялся до бесконечности, и мог бы завершиться только по break. На самом деле в паскале есть специальное слово true, которое обозначает условие, которое всегда верно (и симметричное слово false, которое обозначает условие, которое не верно никогда). Соответственно, еще лучше писать while true do.
Этот вариант свободен от всех указанных выше недостатков. Каждая итерация работает с очередным числом, код считывания не дублируется, код проверки не дублируется, общая последовательность действий понятна, и основная ветка выполнения цикла находится в основном коде.
Вот так и следует писать любые циклы, в которых проверка условия нужна в середине тела цикла:
while true do begin что-то сделали if надо завершить работу then break; сделали что-то еще end;