Изучаем Python — страница 18 из 61


Цикл for получает коллекцию элементов и выполняет блок кода по одному разу для каждого элемента в коллекции. В отличие от него, цикл while продолжает выполняться, пока остается истинным некоторое условие.

Цикл while в действии


Цикл while может использоваться для перебора числовой последовательности. Например, следующий цикл считает от 1 до 5:

counting.py

current_number = 1

while current_number <= 5:

. .print(current_number)

. .current_number += 1

В первой строке отсчет начинается с 1, для чего current_number присваивается значение 1. Далее запускается цикл while, который продолжает работать, пока значение current_number остается меньшим или равным 5. Код в цикле выводит значение current_number и увеличивает его на 1 командой current_number += 1. (Оператор += является сокращенной формой записи для current_number = current_number + 1.)

Цикл повторяется, пока условие current_number <= 5 остается истинным. Так как 1 меньше 5, Python выводит 1, а затем увеличивает значение на 1, отчего current_number становится равным 2. Так как 2 меньше 5, Python выводит 2 и снова прибавляет 1 и т.д. Как только значение current_number превысит 5, цикл останавливается, а программа завершается:

1

2

3

4

5

Очень многие повседневные программы содержат циклы while. Например, представьте компьютерную игру: цикл while выполняется, пока игра продолжается, и завершается, как только игрок захочет остановить игру. Вряд ли кого-нибудь обрадует, если программа завершает работу преждевременно или продолжает работать, когда ей приказали остановиться, так что циклы while весьма полезны.

Пользователь решает прервать работу программы


Программа parrot.py может выполняться, пока пользователь не захочет остановить ее, — для этого бульшая часть кода заключается в цикл while. В программе определяется признак завершения, и программа работает, пока пользователь не введет нужное значение:

parrot.py

(1) prompt = "\nTell me something, and I will repeat it back to you:"

prompt += "\nEnter 'quit' to end the program. "

(2)message = ""

(3)while message != 'quit':

. .message = input(prompt)

. .print(message)

В точке (1) определяется сообщение, которое объясняет, что у пользователя есть два варианта: ввести сообщение или ввести признак завершения (в данном случае это строка 'quit'). Затем переменной message (2) присваивается значение, введенное пользователем. В программе переменная message инициализируется пустой строкой "", чтобы значение проверялось без ошибок при первом выполнении строки while. Когда программа только запускается и выполнение достигает команды while, значение message необходимо сравнить с 'quit', но пользователь еще не вводил ­никакие данные. Если у Python нет данных для сравнения, продолжение выполнения становится невозможным. Чтобы решить эту проблему, необходимо предоставить message исходное значение. И хотя это всего лишь пустая строка, для Python такое значение выглядит вполне осмысленно; программа сможет выполнить сравнение, на котором основана работа цикла while. Цикл while (3) выполняется, пока значение message не равно 'quit'.

При первом выполнении цикла message содержит пустую строку, и Python входит в цикл. При выполнении команды message = input(prompt) Python отображает подсказку и ожидает, пока пользователь введет данные. Эти данные сохраняются в message и выводятся командой print; после этого Python снова проверяет условие команды while. Пока пользователь не введет слово 'quit', приглашение будет выводиться снова и снова, а Python будет ожидать новых данных. При вводе слова 'quit' Python перестает выполнять цикл while, а программа завершается:

Tell me something, and I will repeat it back to you:

Enter 'quit' to end the program. Hello everyone!

Hello everyone!


Tell me something, and I will repeat it back to you:

Enter 'quit' to end the program. Hello again.

Hello again.


Tell me something, and I will repeat it back to you:

Enter 'quit' to end the program. quit

quit

Программа работает неплохо, если не считать того, что она выводит слово 'quit', словно оно является обычным сообщением. Простая проверка if решает проблему:

prompt = "\nTell me something, and I will repeat it back to you:"

prompt += "\nEnter 'quit' to end the program. "

message = ""

while message != 'quit':

message = input(prompt)

. .

. .if message != 'quit':

print(message)

Теперь программа проводит проверку перед выводом сообщения и выводит сообщение только в том случае, если оно не совпадает с признаком завершения:

Tell me something, and I will repeat it back to you:

Enter 'quit' to end the program. Hello everyone!

Hello everyone!


Tell me something, and I will repeat it back to you:

Enter 'quit' to end the program. Hello again.

Hello again.


Tell me something, and I will repeat it back to you:

Enter 'quit' to end the program. quit

Флаги


В предыдущем примере программа выполняла некоторые операции, пока заданное условие оставалось истинным. А что если вы пишете более сложную программу, выполнение которой может прерываться по нескольким разным условиям?

Например, компьютерная игра может завершаться по разным причинам: у игрока кончились все «жизни»; прошло отведенное время; все города, которые он должен был защищать, были уничтожены и т.д. Игра должна завершаться при выполнении любого из этих условий. Попытки проверять все возможные условия в одной команде while быстро усложняются и становятся слишком громоздкими.

Если программа должна выполняться только при истинности нескольких условий, определите одну переменную-флаг. Эта переменная сообщает, должна ли программа выполняться далее. Программу можно написать так, чтобы она продолжала выполнение, если флаг находится в состоянии True, и завершалась, если любое из нескольких событий перевело флаг в состояние False. В результате в команде while достаточно проверить всего одно условие: находится ли флаг в состоянии True. Все остальные проверки (которые должны определить, произошло ли событие, переводящее флаг в состояние False) удобно организуются в остальном коде.

Добавим флаг в программу parrot.py из предыдущего раздела. Этот флаг, который мы назовем active (хотя переменная может называться как угодно), управляет тем, должно ли продолжаться выполнение программы:

prompt = "\nTell me something, and I will repeat it back to you:"

prompt += "\nEnter 'quit' to end the program. "


(1) active = True

(2)while active:

. .message = input(prompt)

. .

(3) . .if message == 'quit':

. . . .active = False

(4) . .else:

. . . .print(message)

В точке (1) переменной active присваивается True, чтобы программа начинала работу в активном состоянии. Это присваивание упрощает команду while, потому что в самой команде while никакие сравнения не выполняются; вся логика реализуется в других частях программы. Пока переменная active остается равной True, цикл выполняется.

В команде if внутри цикла while значение message проверяется после того, как пользователь введет данные. Если пользователь ввел строку 'quit' (3), флаг active переходит в состояние False, а цикл while останавливается. Если пользователь ввел любой текст, кроме 'quit' (4), то введенные им данные выводятся как сообщение.

Результаты работы этой программы ничем не отличаются от предыдущего примера, в котором условная проверка выполняется прямо в команде while. Но теперь в программе имеется флаг, указывающий, находится ли она в активном состоянии, и вы сможете легко добавить новые проверки (в форме команд elif) для событий, с которыми переменная active может перейти в состояние False. Это может быть удобно в сложных программах — например, в компьютерных играх с многочисленными событиями, каждое из которых может привести к завершению программы. Когда по любому из этих событий флаг active переходит в состояние False, основной игровой цикл прервется, выводится сообщение о завершении игры, и у игрока появляется возможность сыграть еще раз.

Команда break и выход из цикла


Чтобы немедленно прервать цикл while без выполнения оставшегося кода в цикле независимо от состояния условия, используйте команду break. Команда break управляет ходом выполнения программы; она позволит вам управлять тем, какая часть кода выполняется, а какая нет.

Рассмотрим пример — программу, которая спрашивает у пользователя, в каких городах он бывал. Чтобы прервать цикл while, программа выполняет команду break, как только пользователь введет значение 'quit':

cities.py

prompt = "\nPlease enter the name of a city you have visited:"

prompt += "\n(Enter 'quit' when you are finished.) "


(1) while True:

. .city = input(prompt)

. .

. .if city == 'quit':

. . . .break

. .else:

. . . .print("I'd love to go to " + city.title() + "!")

Цикл, который начинается с while True (1) , будет выполняться бесконечно — если только в нем не будет выполнена команда break. Цикл в программе продолжает запрашивать у пользователя названия городов, пока пользователь не введет строку 'quit'. При вводе строки 'quit' выполняется команда break, по которой Python выходит из цикла:

Please enter the name of a city you have visited:

(Enter 'quit' when you are finished.) New York

I'd love to go to New York!


Please enter the name of a city you have visited:

(Enter 'quit' when you are finished.) San Francisco

I'd love to go to San Francisco!


Please enter the name of a city you have visited:

(Enter 'quit' when you are finished.) quit

примечание

Команда break может использоваться в любых циклах Python. Например, ее можно включить в цикл for для перебора элементов словаря.

Команда continue и продолжение цикла


Вместо того чтобы полностью прерывать выполнение цикла без выполнения оставшейся части кода, вы можете воспользоваться командой continue для возвращения к началу цикла и проверке условия. Например, возьмем цикл, который считает от 1 до 10, но выводит только нечетные числа в этом диапазоне:

counting.py

current_number = 0

while current_number < 10:

(1) . .current_number += 1

. .if current_number % 2 == 0:

. . . .continue

. .

. .print(current_number)

Сначала переменной current_number присваивается 0. Так как значение меньше 10, Python входит в цикл while. При входе в цикл счетчик увеличивается на 1 в точке (1) , поэтому current_number принимает значение 1. Затем команда if проверяет остаток от деления current_number на 2. Если остаток равен 0 (это означает, что current_number делится на 2), команда continue приказывает Python проигнорировать оставшийся код цикла и вернуться к началу. Если счетчик не делится на 2, то оставшаяся часть цикла выполняется, и Python выводит текущее значение счетчика:

1

3

5

7

9

Предотвращение зацикливания


У каждого цикла while должна быть предусмотрена возможность завершения, чтобы цикл не выполнялся бесконечно. Например, следующий цикл считает от 1 до 5:

counting.py

x = 1

while x <= 5:

. .print(x)

. .x += 1

Но если случайно пропустить строку x += 1 (см. далее), то цикл будет выполняться бесконечно:

# Бесконечный цикл!

x = 1

while x <= 5:

. .print(x)

Теперь переменной x присваивается начальное значение 1, но это значение никогда не изменяется в программе. В результате проверка условия x <= 5 всегда дает результат True, и цикл while выводит бесконечную серию единиц:

1

1

1

1

Любой программист время от времени пишет бесконечный цикл, особенно если в программе используются неочевидные условия завершения. Если ваша программа зациклилась, нажмите Ctrl+C или просто закройте терминальное окно с выводом программы.

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

примечание

В некоторых редакторах — например, в Sublime Text — используется встроенное окно вывода. Оно может усложнить прерывание бесконечных циклов; возможно, для выхода из цикла придется закрыть редактор.

Упражнения

7-4. Дополнения для пиццы: напишите цикл, который предлагает пользователю вводить дополнения для пиццы до тех пор, пока не будет введено значение 'quit’. При вводе каждого дополнения выведите сообщение о том, что это дополнение включено в заказ.

7-5. Билеты в кино: кинотеатр установил несколько вариантов цены на билеты в зависимости от возраста посетителя. Для посетителей младше 3 лет билет бесплатный; в возрасте от 3 до 12 билет стоит $10; наконец, если возраст посетителя больше 12, билет стоит $15. Напишите цикл, который предлагает пользователю ввести возраст и выводит цену билета.

7-6. Три выхода: напишите альтернативную версию упражнения 7-4 или упражнения 7-5, в которой каждый пункт следующего списка встречается хотя бы один раз.

• Завершение цикла по проверке условия в команде while.

• Управление продолжительностью выполнения цикла в зависимости от переменной active.

• Выход из цикла по команде break, если пользователь вводит значение ‘quit’.

7-7. Бесконечный цикл: напишите цикл, который никогда не завершается, и выполните его. (Чтобы выйти из цикла, нажмите Ctrl+C или закройте окно с выводом.)

Использование цикла while со списками и словарями