Что такое цикл в Python
01-03-2023Время чтения ~ 6 мин.Python 2344

Python предлагает для организации циклов всего две конструкции: while и for. Теоретически мы можем организовать ещё цикл с помощью рекурсии, но это сложный подход. Сам по себе цикл достаточно прост для понимания, но на самом деле за ним скрываются сложные алгоритмы.
Нужно понимать, что когда мы говорим о циклах, то в первую очередь речь идёт об алгоритме программы, а не о синтаксической конструкции языка. В программировании очень важно знать возможности языка и применять их под свою задачу. Рассмотрим какие вообще могут быть циклы и то, как их использовать в Python'е.
Цикл while
Такой цикл есть в наверное в любом языке программирования. Вот пример на Python:
i = 1
while i < 10:
print(i)
i = i + 1
Цикл while работает с условием: пока оно истинно, цикл будет выполняться. Перед началом такого цикла следует задать начальные условия — в нашем примере это переменная i, которая используется для обслуживания цикла.
Хотя такой цикл кажется естественным, но на самом деле это развитие немного другой концепции, о которой практически не говорят в языках высокого уровня. Это выглядит странно, но на самом деле на самом низком уровне — в процессоре или его языке Ассемблере — никаких циклов не существует. Вместо это используются метки и операторы условного и безусловного перехода.
В Python нет подобной возможности, поэтому я приведу пример на PHP, показывающий полный аналог цикла while:
$i = 1;
start:
if ($i < 10) {
print($i);
$i = $i + 1;
goto start;
}
Здесь метка start: отмечает начало блока, а командой goto мы переходим к ней после проверки условия. Именно такой код лёг в основу while — цикл с условием.
Цикл с постусловием do..while
Этот цикл похож на предыдущий, только условие проверяется в конце блока цикла. В python нет такого цикла, поэтому опять приведу пример на PHP:
$i = 0;
do {
echo $i;
$i = $i + 1;
} while ($i < 10);
Особенностью этого цикла будет то, что он выполнится как минимум один раз (до проверки условия). Поскольку в Pythone такого цикла нет, то для его имитации потребуется написать что-то вроде такого:
i = 1
print(i)
i = i + 1
while i < 10:
print(i)
i = i + 1
То есть тело цикла нужно выполнить перед самим циклом, чтобы гарантировать минимальное выполнение задачи. Понятно, что такой подход неоптимальный, поэтому для гарантированного срабатывания цикла можно использовать дополнительный флаг в условии, который после срабатывает как тригер.
i = 10 # если число больше 9, то цикл должен сработать один раз
flag = True
while flag or i < 10:
print(i)
i = i + 1
flag = False
Таким образом мы получаем гарантированное срабатывание цикла хотя бы один раз. Такой вариант удобен тем, что в качестве флага можно использовать любые дополнительные условия. Если же нужен «чистый» цикл do..while, то он использует команду break для принудительного завершения:
i = 1
while True:
print(i)
i = i + 1
if i > 10: break
Это т.н. бесконечный цикл, поскольку в его условии используется True. Лучше всё-таки стараться избегать бесконечных циклов, поскольку нужен дополнительный код для его управления. И если условие выхода (там где break) будет зависеть от разных факторов, то есть риск, что оно не сработает и программа зависнет.
Цикл for..each
Именно такой цикл заложен в Python для конструкции for. Это цикл по итерируемой/упорядоченной последовательности. В Python, как известно всё есть объекты, и какие-то из них могут представлять собой последовательности. В простом виде это означает, что требуется перебрать массив или строку.
for s in 'Hello':
print(s)
То есть итерация происходит для каждого элемента последовательности. В этом плане Python устроен достаточно хитро — он сам определят может ли объект быть итерируемым. Если да, то его можно вывести в цикле.
В других языках, где нет понятия итерируемой последовательности, цикл «for..each» работает по другому. Вначале определяется тип переменной — если это какой-то набор данных, например массив, то определяется его длина и задаётся счётчик, который последовательно будет указывать на каждый элемент набора. Можно написать аналог такого цикла на while:
word = 'Hello'
lenght = len(word)
i = 0
while i < lenght:
print(word[i])
i += 1
Конструкция for в Python берет на себя обслуживание всей жизни цикла. При этом мы можем использовать и более сложные вещи, как например функции-генераторы.
def planet():
yield 'Mercury'
yield 'Venus'
yield 'Mars'
yield 'Jupiter'
yield 'Saturn'
for p in planet():
print(p)
Всё-таки компактный код — сильная сторона Python.
Цикл for (классический)
Хотя Python использует for, но на самом деле эта команда в большинстве других языков означает цикл со счётчиком. Обратите внимание, как в цикле while мы вынуждены вводить переменную для счётчика. Так вот цикл for как раз призван упростить написание подобного кода. В Python нет такого варианта, но он есть в большинстве других языков. Я приведу пример на PHP (похожие варианты будут в Java, C, JavaScript и т.п.):
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
Здесь for состоит из трех частей:
- в первой части нужно задать счетчик и присвоить ему начальное значение.
- во второй части указывается условие выхода из цикла.
- в третьей указывается выражение, которое изменяет значение счётчика, обычно это инкремент.
По сути этот код представляет собой более удобную форму while. Наверное стоит ещё отметить, что в Pascal'е цикл for ещё интересней, поскольку не нужно задумываться об инкременте («to» указывает на инкремент, а «downto» — это декремент):
for i:=1 to 10 do write(i); for i:=10 downto 1 do write(i);
Возникает вопрос: каким образом можно создать подобный цикл в Python? Очевидное решение — использовать while, но чаще всего используется генераторная функция range().
for i in range(1, 10):
print(i)
С практической точки зрения такой вариант ничем не уступает классическому for, хотя и требует знания этой особенности Python.
Управление циклом
Управление циклом может быть не только в виде условий для выхода, но и с помощью команд принудительной новой итерации (continue) и прерывания цикла (break).
for s in 'spam':
print(s)
if s == 'a':
break
Команда break досрочно прекратит выполнение цикла, даже если он не до конца выполнен. Такой подход часто встречается в «бесконечном» цикле, когда нужно многократно выполнить одну и туже задачу, но добавить возможность её прервать.
while True:
# Запрашиваем у пользователя ввод
expression = input('Введите данные (или Enter для выхода): ')
# Выходим из цикла, если пользователь ввел пустую строку
if not expression:
break
... # делаем что нужно
Команда continue используется для тех случаев, когда в теле цикла нет необходимости выполнять код, который не нужен. Например у нас есть обход большого количества элементов, где каждый из них требует тяжелых вычислений. Но обрабатывать нужно не все элементы, а только каждый пятый (или любое другое условие). Таким образом мы используем continue для для того, чтобы принудительно начать новую итерацию и проигнорировать код цикла ниже.
for i in range(1, 100):
if i % 5 != 0:
continue
print(i) # какие-то вычисления
Особенностью Python является то, что он позволяет использовать ветку else для циклов. Она выполнится, если в цикле не было break:
i = 1
while i < 5:
print(i)
i = i + 1
else:
print('Сработало else')
Если в цикл добавить break, то сообщение не будет выводиться. Такая возможность годится больше для отладки и перехвата особых ситуаций, поэтому в обычной практике мало используется.