Циклы с условиями
В предыдущем разделе мы научились использовать цикл while True, чтобы повторять участки кода. В такой конструкции условие цикла равно True, поэтому оно выполняется каждый раз. Чтобы избежать бесконечного цикла, нам приходилось явно выходить из цикла с помощью break. Например:
# Print numbers until the variable a equals 5
a = 1
while True:
print(a)
a += 1
if a == 5:
break1 2 3 4
Конечно, условие не обязано всегда быть True: в качестве условия можно использовать любое булево выражение. Общая структура инструкции while выглядит так:
while <condition>:
<block>Идея состоит в том, что выполнение снова и снова возвращается к проверке условия: если условие истинно, выполняется код внутри блока. Если в какой-то момент условие становится ложным, выполнение программы продолжается со строки после блока while.
В следующем цикле условие - number < 10. Блок внутри цикла выполняется только если переменная number меньше 10.
number = int(input("Please type in a number: "))
while number < 10:
print(number)
number += 1
print("Execution finished.")Это могло бы вывести:
Please type in a number: 4 4 5 6 7 8 9 Execution finished.
В этой структуре условие всегда проверяется до выполнения блока внутри цикла. Может случиться так, что блок вообще ни разу не выполнится:
Please type in a number: 12 Execution finished.
12 не меньше 10, поэтому программа не выводит ни одного числа.
Инициализация, условие и обновление
Чтобы создать цикл, вам часто нужно включить три отдельных шага: инициализацию, условие и обновление переменных итерации.
Инициализация означает установку начальных значений переменных, которые используются в условии цикла. Такие переменные часто называют переменными итерации или итераторами. Инициализация выполняется до первого входа в цикл. Условие определяет, как долго должен выполняться цикл. Оно задается в самом начале цикла. Наконец, при каждом повторении цикла переменные, участвующие в условии, обновляются, чтобы каждая итерация приближала цикл к завершению. Следующее изображение иллюстрирует эти шаги:
Если отсутствует любой из этих трех компонентов, цикл, скорее всего, не будет работать правильно. Типичная ошибка - пропустить шаг обновления:
number = 1
while number < 10:
print(number)
print("Execution finished.")Здесь значение переменной number никогда не меняется. Программа застревает в бесконечном цикле, и один и тот же фрагмент кода повторяется снова и снова, пока пользователь не остановит выполнение, например нажав Control + C:
1 1 1 1 1 (continued ad infinitum...)
Запись условий
Любое булево выражение или их комбинация является допустимым условием в цикле. Например, следу ющая программа выводит каждое третье число, но только пока число меньше 100 и не делится на 5:
number = int(input("Please type in a number: "))
while number < 100 and number % 5 != 0:
print(number)
number += 3Два примера выполнения программы с разными входными данными:
Please type in a number: 28 28 31 34 37
Please type in a number: 96 96 99
Когда введено 28, цикл заканчивается на числе 37, потому что следующее число - 40, а оно делится на 5. Когда введено 96, цикл заканчивается на числе 99, потому что следующее число - 102, а оно не меньше 100.
Когда вы пишете цикл, нужно убедиться, что выполнение цикла всегда когда-нибудь завершится. Следующая программа либо завершится, либо нет - в зависимости от входных данных:
number = int(input("Please type in a number: "))
while number != 10:
print(number)
number += 2Если введено четное число, равное 10 или меньше, цикл завершится:
Please type in a number: 4 4 6 8
Во всех остальных случаях цикл выполняется бесконечно, потому что переменная уже никак не сможет стать равной 10. Например, входные значения 3 или 12 привели бы к бесконечному циклу.
Советы по отладке
Представьте, что вы пишете немного более сложную программу, например из следующего упражнения, Powers of two. Первые попытки могут выглядеть так:
limit = int(input("Upper limit:"))
number = 1
while number == limit:
# more codeЗдесь программа начинается с чтения входных данных, а затем продолжается наброском цикла и некоторой попыткой записать условие.
Скорее всего, с первой попытки код не будет работать так, как нужно. Возможно, его придется тестировать десятки или даже сотни раз, прежде чем он заработает правильно.
Этот фрагмент кода всегда запрашивает ввод у пользователя, что делает тестирование медленным и неудобным. При каждом тестировании программы нужно вводить данные.
Один способ обойти это - "зашить" входное значение в код на время тестирования:
# let's hard-code the input value for testing
limit = 8 # int(input("Upper limit"))
number = 1
while number == limit:
# more code Когда программа работает с одним зашитым входным значением, ее легко протестировать и с другими зашитыми значениями. Когда кажется, что она работает правильно во всех случаях, ее можно протестировать с вводом от пользователя.
Этот прием работает со многими тестами, которыми оцениваются упражнения этого курса. Если тест сообщает, что программа работает неправильно, когда входное значение, скажем, 42, это значение можно зашить в программу, пока вы ищете источник ошибки:
# the test said the program works incorrectly when the input is 42
limit = 42 # int(input("Upper limit"))
number = 1
while number == limit:
# more codeОтладка с помощью команд вывода уж е несколько раз упоминалась в предыдущей части курса. Программы, которые вам предстоит писать, будут становиться все сложнее по мере продвижения по курсу. Соответственно, объем отладки, скорее всего, тоже будет расти. Частые причины ошибок скрываются в условиях, завершающих циклы: они могут работать правильно для одних входных данных и ломаться для других, и не всегда очевидно почему.
Поэтому самое время включить отладочную печать в свои практики программирования, если вы еще этого не сделали. Инструкции по отладке можно найти в первом и четвертом разделах предыдущей части.
Помимо команд вывода, для отладки можно использовать много других инструментов. Один из них - инструмент визуализации на сайте Python Tutor. Этот инструмент позволяет выполнять код строка за строкой, а также показывает значения, сохраненные в переменных на каждом шаге.
Немного сломанный код из примера отладки в предыдущем разделе визуализи рован в Python Tutor на следующем изображении:
Красная стрелка показывает, где сейчас находится выполнение программы. Инструмент отображает то, что уже было выведено, а также показывает значение каждой переменной на каждом шаге. Выполнение продвигается вперед строка за строкой, когда вы нажимаете Next.
Чтобы воспользоваться инструментом визуализации, достаточно скопировать свой код и вставить его в окно кода инструмента. У инструмента есть некоторые ограничения по сравнению с версией Python, используемой в этом курсе. Если вы столкнетесь с непонятными сообщениями об ошибках, возможно, лучше попро бовать другой метод отладки.
Более опытные программисты редко активно пользуются инструментом визуализации, но для новичка он может быть ценной помощью. В программировании как дисциплине почти нет места удаче или случайности. Важно, чтобы программист понимал, какие значения создаются его кодом в любой конкретный момент выполнения. Если значения, сохраненные в переменных, не такие, как ожидалось, в программе, скорее всего, есть ошибка.
Инструмент визуализации и отладочные команды вывода - два отличных способа для программиста увидеть собственными глазами, что программа делает именно то, что от нее ожидалось.
Построение строк
В самую первую неделю курса мы узнали, что строки можно "строить" из более коротких строк с помощью оператора +. Например, это корректный код Python:
words = "pride"
words = words + ", prejudice"
words = words + " and python"
print(words)pride, prejudice and python
Оператор += позволяет записать это немного компактнее:
words = "pride"
words += ", prejudice"
words += " and python"
print(words)Это также относится к f-строкам, что может пригодиться, если значения, сохраненные в переменных, нужны как части итоговой строки. Например, эт о сработает:
course = "Introduction to Programming"
grade = 4
verdict = "You have received "
verdict += f"the grade {grade} "
verdict += f"from the course {course}"
print(verdict)You have received the grade 4 from the course Introduction to Programming
В предыдущем упражнении вы вычисляли сумму последовательных чисел, каждый раз добавляя новое значение внутри цикла.
Точно такая же идея применима и к строкам: внутри цикла можно добавлять к строке новые части. Этот прием должен пригодиться в следующем упражнении.
Текущие баллы можно посмотреть в синем индикаторе в правом нижнем углу страницы.