Круги на полях - используем циклы!

Что такое цикл?

Что такое цикл? Проще всего начать, как это ни странно, с симпсонов. В заставке к сериалу один из героев, Барт, каждый раз пишет одну и ту же строку на доске множество раз.

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

print("Я устал от одинаковых команд")
print("Я устал от одинаковых команд")
print("Я устал от одинаковых команд")
print("Я устал от одинаковых команд")
print("Я устал от одинаковых команд")
print("Я устал от одинаковых команд")
# и так далее, и так далее, и так далее

В коде выше мы видим множество одинаковых команд, которые приходится просто копировать. Допустимо ли это? Возможно, но только не в программировании! Я уже как то говорил, что основной мотор для развития языков программирования - это лень программистов. Если какую-то задачу можно упростить, то рано или поздно так и будет сделано. Звучит абсурдно, но если тратить меньше времени на простые задачи, то можно сделать больше за то же время, а значит - получить больший доход.

Когда в программе используются похожие участки кода, программисты стараются разными способами от них избавиться, это называется повторным использованием кода. Для этого используется множество разных способов, таких как создание функций, выделение функций в модули, использование наследования в ООП и тд. Но самый простой и самый действенный - это использование циклов.

Цикл — разновидность управляющей конструкции в высокоуровневых языках программирования, предназначенная для организации многократного исполнения набора инструкций.

В питоне есть два вида циклов - while и for, и сначала мы познакомимся именно с while. В переводе на русский, while - это пока. Логически конструкция выглядит так:

while условие:
    повторяемый код
    повторяемый код

Часть кода, которая повторяется в цикле, называется телом цикла, а одно повторение - итерацией цикла.

Как видишь, структура цикла очень похожа на условный оператор if - тот же отступ внутри блока и двоеточие после условия. Но если условный оператор выполняет код если условие верно, то цикл выполняет его пока условие верно.

Цикл с заранее известным числом итераций

Рассмотрим задачу с робо-Бартом. Предположим, что строку нужно повторить 10 раз.

Решение на Python будет выглядеть так:

i = 0
while i < 10:
    print("Повторяем строку", i, "раз!")
    i = i + 1

Результат:

Повторяем строку 0 раз!
Повторяем строку 1 раз!
Повторяем строку 2 раз!
Повторяем строку 3 раз!
Повторяем строку 4 раз!
Повторяем строку 5 раз!
Повторяем строку 6 раз!
Повторяем строку 7 раз!
Повторяем строку 8 раз!
Повторяем строку 9 раз!

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

Счетчик - переменная, в которой хранится количество уже выполненных на данный момент итераций цикла.

Цикл в таком случае выглядит, как "пока счетчик меньше нужного значения, повторить тело".

В нашем примере выше, счетчик - это переменная i. В качестве имен для счетчиков обычно используются буквы i, j или k, но на логику программы это не влияет. Счетчик - это совершенно обычная переменная, в которой лежит числовое значение.

Заранее известное значение - это не обязательно число, это может быть и переменная. Например, вот так мы можем посчитать сумму чисел в заданном промежутке:

summa = 0
start = int(input("Нижняя граница: "))
end = int(input("Верхняя граница: "))

while start <= end:
    summa = summa + start
    start = start + 1

print(summa)

Результат:

Нижняя граница: 50
Верхняя граница: 100
3825

Будьте внимательны! Самая частая ошибка - это забыть изменить значение счетчика в конце итерации. В таком случае ваш цикл будет повторяться вечно, и программа никогда не завершится.

Циклы с неизвестным числом итераций

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

answer = ""
while answer.lower() != "да":
    print("Вы согласны с лицензионным соглашением? (да/нет):")
    answer = input()

В данном случае цикл будет повторяться, пока пользователь не введет "да". Кстати, что делает .lower()? Очень просто - делает все буквы в строке строчными.

Вечный цикл, break и continue

Иногда цикл бывает удобно записать, как вечный, а затем при каких-то условиях выйти из него. Выглядит это так:

while True:
    print("Вы согласны с лицензионным соглашением? (да/нет):")
    answer = input()
    if answer.lower() != "да":
        break

print("Мы рады, что вы согласны!")

True - это истина. Т.е. условие while True всегда истинно, и цикл сам по себе никогда не закончится. Но ему можно помочь.

  • команда break прерывает цикл, в котором находится.
  • команда continue переводит нас на следующую итерацию цикла (в цикле while - просто возвращает в к началу итерации).

Например, если мы хотим вывести числа до 100, которые не делятся на 3 и 5, можно сделать так:

i = 0

while True:
    # если число делится на 3 или на 5 - пропускаем его
    if i % 3 == 0 or i % 5 == 0:
        continue
    # если дошли до 100 - тормозим
    if i == 100:
        break

    print(i)

    i += 1

Отличный способ применить это на практике - доделать нашу старую задачу с игрой в "угадай число".

Программа загадывает пользователю число от 1 до 50, и пока он не отгадает его, дает подсказки "больше-меньше". Вот только теперь для отгадывания числа должно быть ограниченное количество попыток, а после завершения раунда (если число отгадано или попытки закончились) игра должна, при желании пользователя, загадывать новое число. А еще можно запоминать рекордное число попыток среди всех раундов в этой игре.