Часто в программах требуется выполнять одни и те же действия многократно. Допустим, нам нужно написать программу проверки пароля для входа в систему (следует учесть, что это всего лишь пример и в настоящих системах пользователь авторизуется по логину и паролю, а сам пароль не хранится в открытом виде).
Пользователь вводит пароль, а система разрешит вход, если пароль верный, а если нет — попросит ввести его снова. Для реализации программы недостаточно использовать только условный оператор, так как он позволит провести проверку только один раз. На помощь нам приходит цикл — он позволяет выполнять код многократно:
saved_pwd = "right_password"
pwd = input("Введите пароль для входа: ")
while pwd != saved_pwd:
pwd = input("Введите пароль для входа: ")
print("Пароль верный. Вход разрешён.")
В программе применяется цикл while
, в котором используется условие для проверки продолжения цикла. Другими словами, пока выполняется условие, цикл продолжает работать. Условие необходимо для того, чтобы цикл не был бесконечным. Тело цикла — это код, который будет выполняться многократно. Синтаксис языка Python требует, чтобы тело цикла записывалось с отступом в четыре пробела (использование табуляций крайне не рекомендуется).
Каждый повтор, или шаг, цикла называется итерацией. Как только условие продолжения нарушено, цикл останавливается и программа продолжает работу со следующей за циклом строчки.
В предыдущем примере мы можем вообще обойтись без переменной pwd
, так как она используется только в проверке условия продолжения цикла:
saved_pwd = "right_password"
while input("Введите пароль для входа: ") != saved_pwd:
pass
print("Пароль верный. Вход разрешён.")
Обратите внимание, что внутри тела цикла была использована пустая инструкция pass
.
Она ничего не делает в программе и нужна для соответствия кода синтаксису языка, так как тело цикла не может быть пустым (иначе будет синтаксическая ошибка и программа не будет работать).
В Python версии 3.8 появился моржовый оператор (walrus operator). Он записывается как :=
и позволяет одновременно вычислить выражение, присвоить результат переменной и вернуть это значение, например в условие.
Давайте напишем программу, которая будет здороваться со всеми людьми, чьи имена введёт пользователь. Сигнал для остановки — ввод строки «СТОП»:
name = input("Введите имя: ")
while name != "СТОП":
print(f"Привет, {name}!")
name = input("Введите имя: ")
print("Программа завершена.")
А теперь перепишем эту программу с использованием моржового оператора:
while (name := input("Введите имя: ")) != "СТОП":
print(f"Привет, {name}!")
print("Программа завершена.")
Благодаря моржовому оператору из программы были убраны строки, в которых считывалось имя первый раз до цикла, а также в теле цикла. Теперь имя считывается только непосредственно на этапе проверки, выполняется ли условие продолжения цикла.
Итак, цикл while
обычно применяется в тех случаях, когда заранее не известно, сколько итераций будет выполнено, но известно условие, при котором цикл продолжает работу.
Если количество итераций заранее известно, то предпочтительнее использовать цикл for
. Он применяется совместно с итерируемой переменной. Очень часто ей дают имя i
и используют в теле цикла, а её значение изменяется на каждой итерации в соответствии с диапазоном, заданным функцией range()
. Строго говоря, range()
является не функцией, а встроенным типом данных (Built-in Type), представляющим собой последовательность целых чисел. Подробнее про него можно почитать в документации. А мы для простоты изложения будем всё же называть range()
функцией.
Функция range()
может принимать от одного до трёх целочисленных аргументов:
range(n)
— возвращает последовательность целых чисел от 0 до n - 1. Например,range(4)
вернёт последовательность целых чисел: 0, 1, 2, 3;range(k, n)
— возвращает последовательность целых чисел от k до n - 1. Например,range(1, 5)
вернёт последовательность целых чисел: 1, 2, 3, 4;range(k, n, s)
— возвращает последовательность целых чисел от k до n - 1 с шагом s. Например,range(1, 10, 2)
вернёт последовательность целых чисел: 1, 3, 5, 7, 9.
Выведем на экран n целых чисел, начиная с 0 (n вводится пользователем):
n = int(input("Введите количество чисел: "))
for i in range(n):
print(i)
Результат работы программы:
Введите количество чисел: 5 0 1 2 3 4
Выведем на экран целые числа в диапазоне от k до n - 1 (k, n вводятся пользователем):
k = int(input("Введите начало диапазона: "))
n = int(input("Введите конец (без включения) диапазона: "))
for i in range(k, n):
print(i)
Результат работы программы:
Введите начало диапазона: 2 Введите конец (без включения) диапазона: 5 2 3 4
Выведем на экран целые чётные числа в диапазоне от 0 до n (n вводится пользователем):
n = int(input("Введите конец диапазона: "))
for i in range(0, n + 1, 2):
print(i)
Результат работы программы:
Введите конец диапазона: 5 0 2 4
Используя в функции range()
отрицательный шаг, можно запустить цикл в обратном порядке:
n = int(input("Введите первое число: "))
for i in range(n, -1, -1):
print(i)
Результат работы программы:
Введите первое число: 5 5 4 3 2 1 0
Попробуем указать параметры диапазона, в который не попадёт ни одно число. Например, range(1, 5, -1)
или range(10, 1, 2)
. Как можно видеть, ошибка не произойдёт, а функция range()
просто вернёт пустую последовательность чисел. Если попытаться пройти в цикле по такой пустой последовательности, то не будет выполнено ни одной итерации:
for i in range(1, 5, -1):
print(i)
Обратите внимание: изменение значения итерируемой переменной внутри тела цикла не имеет смысла, так как будет перезаписано на следующей итерации очередным значением из диапазона функции range()
. Например, следующий код по-прежнему выведет числа от 0 до n - 1, несмотря на изменение значения итерируемой переменной в теле цикла:
n = int(input("Введите n: "))
for i in range(n):
print(i)
i = 100
Результат работы программы:
Введите n: 5 0 1 2 3 4