Сайт вебмастера

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

Related Posts