Что такое цикл в Python
01-03-2023Reading time ~ 6 min.Python 1411
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
, то сообщение не будет выводиться. Такая возможность годится больше для отладки и перехвата особых ситуаций, поэтому в обычной практике мало используется.