Простые циклы
Теперь мы довольно подробно рассмотрели условные конструкции. Еще одна центральная техника в программировании - повторение, или итерация. Вместе они образуют фундаментальные управляющие структуры, которыми должен владеть каждый программист. Они называются управляющими структурами, потому что по сути позволяют управлять тем, какие строки кода выполняются и когда. Условные структуры позволяют выбирать между частями кода, а итерационные структуры позволяют повторять части кода. Их часто называют циклами, потому что они позволяют программе "вернуться" к строке, которая уже выполнялась ранее. Процесс выполнения одного повторения цикла также называют итерацией цикла.
В этом разделе представлен простой цикл while. Его структура похожа на условные операторы, которые мы уже рассмотрели. В следующей части мы углубимся в более сложные примеры.
Посмотрим на программу, которая просит пользователя ввести число, а затем выводит квадрат этого числа. Это продолжается, пока пользователь не введет -1.
while True:
number = int(input("Please type in a number, -1 to quit: "))
if number == -1:
break
print(number ** 2)
print("Thanks and bye!")Запуск программы может выглядеть так:
Please type in a number, -1 to quit: 2 4 Please type in a number, -1 to quit: 4 16 Please type in a number, -1 to quit: 10 100 Please type in a number, -1 to quit: -1 Thanks and bye!
Как видно выше, программа спрашивает несколько чисел благодаря оператору while в программе. Когда пользователь вводит -1, выполняется команда break, которая выходит из цикла, и выполнение продолжается с первой строки после блока while.
При работе с циклами крайне важно, чтобы в коде всегда был способ выйти из цикла в какой-то момент, иначе повторение может продолжаться бесконечно. Чтобы показать это, немного изменим пример выше:
number = int(input("Please type in a number, -1 to quit: "))
while True:
if number == -1:
break
print(number ** 2)
print("Thanks and bye!")В этой версии программа просит пользователя ввести число вне цикла. Если пользователь вводит любое число, кроме -1, из цикла никогда не происходит выход. Это образует бесконечный цикл, что означает, что блок кода внутри цикла повторяется бесконечно:
Please type in a number, -1 to quit: 2 4 4 4 4 4 4 4 4 (continued ad infinitum...)
Следующая программа имеет структуру, похожую на пример выше до бесконечного цикла, но пользовательский опыт совсем другой. Эта программа позволяет пользователю продолжить только если он вводит правильный PIN 1234:
while True:
code = input("Please type in your PIN: ")
if code == "1234":
break
print("Incorrect...try again")
print("Correct PIN entered!")Please type in your PIN: 0000 Incorrect...try again Please type in your PIN: 9999 Incorrect...try again Please type in your PIN: 1234 Correct PIN entered!
Циклы и вспомогательные переменные
Сделаем пример проверки PIN немного более реалистичным. Эта версия дает пользователю только три попытки ввести PIN.
Программа использует две вспомогательные переменные. Переменная attempts отслеживает, сколько раз пользователь вводил PIN. Переменная success получает значение True или False в зависимости от того, удалось ли пользователю войти.
attempts = 0
while True:
code = input("Please type in your PIN: ")
attempts += 1
if code == "1234":
success = True
break
if attempts == 3:
success = False
break
# this is printed if the code was incorrect AND there have been less than three attempts
print("Incorrect...try again")
if success:
print("Correct PIN entered!")
else:
print("Too many attempts...")Please type in your PIN: 0000 Incorrect...try again Please type in your PIN: 1234 Correct PIN entered!
Please type in your PIN: 0000 Incorrect...try again Please type in your PIN: 9999 Incorrect...try again Please type in your PIN: 4321 Too many attempts...
Выход из цикла происходит либо когда пользователь вводит правильный PIN, либо когда попыток стало слишком много. Оператор if после цикла проверяет значение переменной success и выв одит соответствующее сообщение.
Отладочные команды вывода в циклах
Добавление циклов в программы также увеличивает количество возможных источников ошибок. Становится еще важнее освоить использование отладочных команд вывода, представленных в первом разделе этой части.
Посмотрим на программу, почти идентичную предыдущему примеру, но с одним важным отличием:
attempts = 0
while True:
code = input("Please type in your PIN: ")
attempts += 1
if attempts == 3:
success = False
break
if code == "1234":
success = True
break
print("Incorrect...try again")
if success:
print("Correct PIN entered!")
else:
print("Too many attempts...")Эта версия ведет себя странно, когда пользователь вводит правильный код с третьей попытки:
Please type in your PIN: 0000 Incorrect...try again Please type in your PIN: 9999 Incorrect...try again Please type in your PIN: 1234 Too many attempts...
Итак, попробуем найти причину, добавив несколько стратегических отладочных команд вывода внутри цикла:
while True:
print("beginning of the while block:")
code = input("Please type in your PIN: ")
attempts += 1
print("attempts:", attempts)
print("condition1:", attempts == 3)
if attempts == 3:
success = False
break
print("code:", code)
print("condition2:", code == "1234")
if code == "1234":
success = True
break
print("Incorrect...try again")beginning of the while block: Please type in your PIN: 2233 attempts: 1 condition1: False code: 2233 condition2: False Incorrect...try again beginning of the while block: Please type in your PIN: 4545 attempts: 2 condition1: False code: 4545 condition2: False Incorrect...try again beginning of the while block: Please type in your PIN: 1234 attempts: 3 condition1: True Too many attempts...
Из выводов выше видно, что во время третьей итерации цикла условие первого оператора if равно True, и происходит выход из цикла. Эта итерация никогда не доходит до второго оператора if, который проверяет, был ли код введен правильно:
while True:
# ....
# this block is executed too early
if attempts == 3:
success = False
break
# the third iteration never gets this far
if code == "1234":
success = True
breakПорядок условных операторов или разных ветвей внутри условного оператора - частая причина ошибок, особенно в циклах. Отладочные команды вывода часто являются самым простым способом найти их причину.
Конкатенация строк с оператором +
В примере выше с проверкой PIN использовалась вспомогательная переменная attempts, чтобы отслеживать, сколько раз пользователь пытался ввести код:
attempts = 0
while True:
code = input("Please type in your PIN: ")
attempts += 1
# ...Переменная устанавливается в ноль вне цикла, и каждая итерация увеличивает ее значение на единицу.
Похожая идея увеличения работает и со строковыми переменными. Например, программа могла бы отслеживать все PIN-коды, которые вводил пользователь:
codes = ""
attempts = 0
while True:
code = input("Please type in your PIN: ")
attempts += 1
codes += code + ", "
# ...Вспомогательная переменная инициализируется пустой строкой, то есть строкой без символов:
codes = ""С каждой итерацией строка становится длиннее, потому что к ней добавляется код, введенный пользователем, вместе с запятой:
code = input("Please type in your PIN: ")
codes += code + ", "Если пользователь вводит коды 1111 2222 1234, в конце выполнения программы значение codes будет
1111, 2222, 1234,
Ответьте на короткий опросник по материалам этой недели.
Текущие баллы можно посмотреть в синем индикаторе в правом нижнем углу стра ницы.