Цикл while в питоне

Цикл while («пока») позволяет выполнить одну и ту же последовательность действий, пока проверяемое условие истинно. Условие записывается до тела цикла и проверяется до выполнения тела цикла. Как правило, цикл while используется, когда невозможно определить точное значение количества проходов исполнения цикла.

Синтаксис цикла while в простейшем случае выглядит так:

while условие:
    блок инструкций

При выполнении цикла while сначала проверяется условие. Если оно ложно, то выполнение цикла прекращается и управление передается на следующую инструкцию после тела цикла while. Если условие истинно, то выполняется инструкция, после чего условие проверяется снова и снова выполняется инструкция. Так продолжается до тех пор, пока условие будет истинно. Как только условие станет ложно, работа цикла завершится и управление передастся следующей инструкции после цикла.

Например, следующий фрагмент программы напечатает на экран все целые числа от 1 до 10. Видно, что цикл while может заменять цикл for ... in range(...):

i = 1
while i <= 10:
    print(i)
    i += 1

В этом примере переменная i внутри цикла изменяется от 1 до 10. Такая переменная, значение которой меняется с каждым новым проходом цикла, называется счетчиком. Заметим, что после выполнения этого фрагмента значение переменной i будет равно 11, поскольку именно при i==11 условие i<=10 впервые перестанет выполняться.

Вот еще один пример использования цикла while для определения количества цифр натурального числа n:

n = int(input())
length = 0
while n > 0:
    n //= 10
    length += 1

В этом цикле мы отбрасываем по одной цифре числа, начиная с конца, что эквивалентно целочисленному делению на 10 (n //= 10), при этом считаем в переменной length, сколько раз это было сделано.

В языке Питон есть и другой способ решения этой задачи, если исходное число n ещё не изменено циклом: length = len(str(n)).

Инструкции управления циклом

После тела цикла можно написать слово else: и после него блок операций, который будет выполнен один раз после окончания цикла, когда проверяемое условие станет неверно:

i = 1
while i <= 10:
    print(i)
    i += 1
else:
    print('Цикл окончен, i =', i)

Казалось бы, никакого смысла в этом нет, ведь эту же инструкцию можно просто написать после окончания цикла. Смысл появляется только вместе с инструкцией break, использование которой внутри цикла приводит к немедленному прекращению цикла, и при этом не исполняется ветка else. Обычно инструкцию break используют внутри if, чтобы завершить цикл при выполнении особого условия.

Другая инструкция управления циклом — continue (продолжение цикла). Если эта инструкция встречается где-то посередине цикла, то пропускаются все оставшиеся инструкции до конца цикла, и исполнение цикла продолжается со следующей итерации. В цикле while это означает повторную проверку условия. Если перед continue не обновить переменные, от которых зависит условие, цикл может стать бесконечным.

Инструкции break, continue и ветка else: можно использовать и внутри цикла for. Тем не менее, увлечение инструкциями break и continue не поощряется, если можно обойтись без их использования. Вот типичный пример плохого использования инструкции break.

while True:
    length += 1
    n //= 10
    if n == 0:
        break

Обработка последовательности в while

Иногда нужно обрабатывать последовательность объектов до тех пор, пока не встретится какой-то «особый» объект. И тут есть два варианта: нужно остановиться после обработки «особого» объекта, либо до.

Ниже приведены условные схемы, а не готовые программы: слова взять_следующий и обработать обозначают действия. Проверка is not подходит для специального объекта-маркера (например, None); при сравнении чисел или строк по значению следует использовать !=.

Если «особый» элемент нужно обработать, то обычно пишут так:

x = любое_не_особое_значение
while x is not особый:
    x = взять_следующий
    обработать

Если «особый» элемент НЕ нужно обрабатывать (то есть нужно остановиться сразу), то обычно пишут так:

x = взять_следующий
while x is not особый:
    обработать
    x = взять_следующий

Первый вариант использования цикла предпочтителен сразу по нескольким причинам. Во-первых, каждая итерация цикла начинается с взятия нового значения. Если мы на предыдущей итерации сделали continue, то в этой итерации сразу всё ок. Во-вторых, значение заполняется ровно в одном месте. Если код для получения нового значения длинный, то он не будет дублироваться. Ну и без дублирования кода нельзя забыть исправить дубль.

Начиная с Python 3.8 можно записать и второй вариант обработки без повторов с помощью выражения присваивания :=, вот так:

while (x := взять_следующий) is not особый:
    обработать