Код
#Руководства

Циклы в Python: как работают и какие бывают

Они есть практически в каждом языке программирования, но в Python с ними работать приятнее всего. Как, впрочем, и со всем остальным.

Иллюстрация: Катя Павловская для Skillbox Media

Код в Python обычно выполняется последовательно: первая строка, потом вторая, третья и так далее. Но некоторые конструкции позволяют нарушать этот порядок, чтобы совершать более сложные операции.

Например, циклы выполняют один и тот же блок кода несколько раз. В Python есть два основных вида циклов: while и for. О них и поговорим.

Содержание


Как работают циклы

Любой цикл состоит из двух обязательных элементов:

  • условие — начальный параметр; цикл запустится только при его выполнении и закончится, как только условие перестанет выполняться;
  • тело — сама программа, которая выполняется внутри цикла.

Схематически его можно представить так:

Инфографика: Майя Мальгина для Skillbox Media

В синтаксисе Python в конце строки с условием ставится двоеточие, а всё тело выделяется отступом (табуляцией или четырьмя пробелами).

программа до цикла
условие:
	первая строка тела
	вторая строка тела
программа после цикла

Цикл while в Python

While — наиболее простой и понятный вид цикла. Его ещё называют циклом с предусловием.

x = 1
while x < 5:
    print(x)
    x += 1  # Означает то же самое, что x = x + 1
>>> 1
>>> 2
>>> 3
>>> 4

С языка Python на русский программу можно перевести так: «Пока икс меньше пяти, печатай икс и прибавляй к нему единицу».

Но в простоте while кроется и опасность: его легко сделать бесконечным. Например, если в коде выше мы уберём x += 1, то получится вот так:

# Этот код будет выполняться бесконечно
x = 1
while x < 5:
    print(x)

Здесь с переменной x ничего не происходит. Она всегда равна единице, поэтому условие цикла никогда не перестанет выполняться. Соответственно, он никогда не завершится.

Чтобы избежать таких ситуаций, при использовании while нужно следить: перестанет ли когда-нибудь выполняться условие? Ещё можно использовать оператор break — о нём мы расскажем чуть позже.

Цикл for в Python

Цикл for программисты используют куда чаще, чем while. Для него мы устанавливаем не условие в чистом виде, а некий массив данных: список, кортеж, строку, словарь, диапазон или любой другой итерируемый объект.

На каждой итерации цикла программа как бы спрашивает: «Остались ли в объекте ещё элементы, по которым я не прошла?»

Допустим, у нас есть список с числами: [14, 101, -7, 0]. Мы можем использовать его вместе с for, чтобы напечатать каждый элемент по отдельности.

num_list = [14, 101, -7, 0]
for number in num_list:
    print(number)
>>> 14
>>> 101
>>> -7
>>> 0

Здесь переменная number обновляется при каждом новом витке цикла. Сначала она хранит в себе первый элемент, потом второй, и так — пока список не закончится.

Как и любую другую переменную, мы могли назвать number как угодно. Часто используют буквы i, j и k. Если внутри цикла мы ни разу не обращаемся к этой переменной, то среди питонистов её принято обозначать символом нижнего подчёркивания _.

Функция range()

Когда нужно применить for к числовому промежутку, его можно задать диапазоном. Для этого используют функцию range(). В неё можно передать от одного до трёх аргументов.

Если аргумент один, то сформируется диапазон от нуля до числа, предшествующего значению аргумента.

for i in range(3):
    print(i)
>>> 0
>>> 1
>>> 2

Если аргумента два, то сформируется диапазон от значения первого аргумента до числа, предшествующего значению второго аргумента.

for i in range(23, 26):
    print(i)
>>> 23
>>> 24
>>> 25

Если аргумента три, то первые два работают, как в прошлом случае. Третий же означает шаг, с которым числа следуют друг за другом.

for i in range(10, 20, 3):
    print(i)
>>> 10
>>> 13
>>> 16
>>> 19

Однострочный цикл: генератор списков

Если в теле цикла for выполняется всего одно действие, синтаксис Python позволяет сократить его запись до:

i for i in iterable_object

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

num_list = [i for i in range(1, 11)]
print(num_list)
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

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

print([i for i in range(1, 11) if i % 2 == 0])
>>> [2, 4, 6, 8, 10]

Конструкция if i % 2 == 0 означает: «если при делении i на 2 остаток равен 0».

С самой переменной i тоже можно проводить операции. Используем предыдущий генератор, но теперь будем выводить не сами чётные числа, а их квадраты.

print([i ** 2 for i in range(1, 11) if i % 2 == 0])
>>> [4, 16, 36, 64, 100]

Главное при таком подходе — сильно не увлекаться. Если код тяжело прочесть и понять (например, когда к i применяется сразу несколько функций и методов и вдобавок задаётся сложное условие), то лучше разбить его на несколько строк. Понятность важнее лаконичности.

Прерывание цикла: ключевое слово break

Бывают случаи, когда нужно завершить цикл принудительно, даже если его условие всё ещё выполняется. В таких случаях используют ключевое слово break.

Возьмём строку Hi, loop! и будем выводить каждый её символ. Если встретим запятую, досрочно завершим цикл.

string = 'Hi, loop!'
for i in string:
    if i == ',':
        break
    print(i)
>>> H
>>> i

Если же в строке запятой не будет, то цикл пройдёт по каждому её символу — и только потом завершится.

string = 'Hi loop!'
for i in string:
    if i == ',':
        break
    print(i)
>>> H
>>> i
>>>  
>>> l
>>> o
>>> o
>>> p
>>> !

Пропуск части цикла: ключевое слово continue

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

Возьмём числа от 1 до 10 включительно и выведем из них только те, которые не делятся ни на 2, ни на 3.

for i in range(1, 10):
    if i%2 == 0 or i%3 == 0:
        continue
    print(i)
>>> 1
>>> 5
>>> 7

Как видим, если срабатывает условие if (то есть если число делится на 2 или на 3 без остатка), то оставшаяся часть тела не работает — и i не печатается.

Последнее действие в цикле: ключевое слово else

Обычно ключевое слово else употребляют в связке с if, но у него есть и другое применение. Его можно использовать вместе с while или for. В таком случае else-код выполнится после того, как пройдут все витки цикла.

Если же цикл досрочно прервётся из-за break, то часть программы в else не выполнится.

Вспомним наш код со строкой Hi, loop! и добавим к нему else.

string = 'Hi, loop!'
for i in string:
    if i == ',':
        break
    print(i)
else:
    print('Цикл завершился без break')
>>> H
>>> i

В строке была запятая, сработал break — не выполнилось else-условие. Теперь уберём из неё запятую и посмотрим, что получится.

string = 'Hi loop!'
for i in string:
    if i == ',':
        break
    print(i)
else:
    print('Цикл завершился без break')
>>> H
>>> i
>>>  
>>> l
>>> o
>>> o
>>> p
>>> !
>>> Цикл завершился без break

Цикл прошёл все свои итерации, завершился самостоятельно, и поэтому код в else выполнился. Он также будет работать, если цикл не совершил ни одного витка.

while 1 == 0:
    print('Эта строка никогда не выполнится')
else:
    print('Цикл завершился без break')
>>> Цикл завершился без break

Бесконечный цикл

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

Чтобы цикл был бесконечным, его условие должно выполняться всегда. Это можно сделать разными способами.

# Способ №1 — «пока истинно»
while True:
	pass  # pass — оператор-заглушка, который ничего не делает

Если сделать while False, то цикл, наоборот, никогда не начнётся.

# Способ №2 — «пока проверяемое значение — любое ненулевое число»
while 1:
	pass
while -4:
	pass
while 2023:
	pass

Если сделать while 0, то цикл никогда не начнётся.

# Способ №3 — «пока проверяемое значение — непустой элемент»
while 'string':
	pass
while [False, 'list', 0]:
	pass

Если после while поставить пустой элемент — например, строку str() или список list(), то цикл никогда не начнётся.

# Способ №4 — корректное уравнение
while 1 == 1:
	pass
while 0 != 1:
	pass

Альтернативный подход — поместить после while переменную, в которой лежит подходящее условие. Например:

# Способ №1
condition = True
while condition:
	pass
# Способ №2
condition = 1
while condition:
	pass
# Способ №3
condition = 'string'
while condition:
	pass

В таких случаях для выхода из цикла можно не использовать оператор break, а заменить значение в переменной condition на False, 0, None или любой пустой элемент. Цикл закончит последний виток и завершится, потому что условие больше не будет выполняться.

Такой подход применяется, когда нужно завершить цикл из других мест программы: например, из функции или вложенного цикла. Ещё одно отличие: так как цикл завершается «естественно», без оператора break, в нём выполнится else-код (если он есть).

condition = True
x = 0
while condition:
    print(x)
    x += 1
    if x == 3:
        condition = False
else:
    print('Цикл завершился без break')
>>> 0
>>> 1
>>> 2
>>> Цикл завершился без break

Как сделать аналог do while в Python

В некоторых языках программирования есть ещё один вид цикла — с постусловием. Он всегда проходит хотя бы один виток и только после этого проверяет, выполняется ли условие. Вот его схема:

Инфографика: Майя Мальгина для Skillbox Media

В Java и C++ такое достигается с помощью конструкции do while, но в Python её нет. Зато можно сделать аналог. Для этого нужно использовать бесконечный цикл, а внутри его тела прописать условие завершения.

x = 12
while True:
    x += 1
    print(x)
    if x > 5:
        break
>>> 13

Каким бы ни было значение x, такой цикл пройдёт хотя бы один виток. А это и есть постусловие.

Вложенные циклы в Python

Циклы в Python можно вкладывать друг в друга — то есть в теле одного цикла вызывать другой. Логика программы при этом усложняется.

Инфографика: Майя Мальгина для Skillbox Media

Можно вкладывать друг в друга сколько угодно циклов. При этом для каждого нового уровня вложенности нужно увеличивать отступ. Выглядит это так:

while condition:
    pass
    while inner_condition:
        pass
    pass

Напишем программу, которая будет выводить номер итерации внешнего и внутреннего цикла.

for i in range(3):
    print(f'Итерация внешнего цикла: {i}')
    for j in range(2):
        print(f'Итерация внутреннего цикла: {j}')
>>> Итерация внешнего цикла: 0
>>> Итерация внутреннего цикла: 0
>>> Итерация внутреннего цикла: 1
>>> Итерация внешнего цикла: 1
>>> Итерация внутреннего цикла: 0
>>> Итерация внутреннего цикла: 1
>>> Итерация внешнего цикла: 2
>>> Итерация внутреннего цикла: 0
>>> Итерация внутреннего цикла: 1

Резюмируем

  • Циклы — один из основных инструментов любого Python-разработчика. С их помощью всего за пару строчек кода можно совершить сразу множество повторяющихся действий.
  • Циклы состоят из условия и тела. Код в теле выполняется только до тех пор, пока соблюдено условие.
  • В Python есть два вида циклов: while и for. В while условие задаётся явным образом. В for перебирается каждый элемент коллекции.
  • К обоим видам можно применять разные операторы: break для прерывания, continue для пропуска части тела, else для совершения последнего действия перед выходом из цикла.
  • Циклы можно делать бесконечными (тогда программа никогда не завершится или завершится только при выполнении определённого условия) и вкладывать друг в друга.

Больше интересного про код в нашем телеграм-канале. Подписывайтесь!

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Python-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована