5.Счетный цикл

В программировании часто возникает необходимость повторять определенные действия несколько раз. Для этих нужд существуют циклы.

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

Рассмотрим код, который напечатает 10 раз слово "Привет": for i in range(10):
print("Привет")

Структура цикла следующая:
for [название_переменной_цикла] in [итерируемый_объект]:
блок кода

Название переменной может быть любым, но если наша переменная обозначает количество итераций (т.е. обозначает количество повторений блока кода), то обычно такую переменную называют i, например, в примере выше количество итераций 10.

Итерируемым объектом может быть объект последовательности, например, список, словарь или кортеж. Вот пример: for i in [1, "a", 6, 2.9]:
print(i)
Вывод:
1
"a"
6
2.9

В данном примере мы видим поочередный вывод всех значений списка.

В первом же случае итерируемый объект - это итерируемая последовательность класса range, которая формируется с помощью функции range. Разберем подробнее: for i in range(5):
print(i)
Вывод:
0
1
2
3
4

В данном случае наша последовательность формируется из чисел от 0 до 5 не включительно.

range формирует последовательность только из чисел в заданном диапозоне. Можно передать в функцию range второй и третий аргумент.

  • range(5) - последовательность от 0 до 5 не включительно. (0, 1, 2, 3, 4)
  • range(3, 9) - последовательность от 3 до 9 не включительно. (3, 4, 5, 6, 7, 8)
  • range(3, 15, 3) - последовательность от 3 до 15 не включительно с шагом 3. (3, 6, 9, 12) Число 15 не включается!
То есть с одним аргументом мы указываем только правую границу последовательность, с двумя - обе границы, с тремя - обе границы и шаг.

for i in range(2, 6):
print(i)
Вывод:
2
3
4
5 for i in range(2, 11, 3):
print(i)
Вывод:
2
5
8

Также мы можем создать последовательность следующего вида: for i in range(6, 1, -1): # последовательность от 6 до 1 не включительно
print(i)
Вывод:
6
5
4
3
2

Мы задали отрицательный шаг, а также указали, что левая граница больше правой.

break, continue, else

Мы можем принудительно остановить цикл с помощью ключевого слова break. Например мы просим пользователя вводить 10 чисел с каждой итерацией, а после их складывать, но если было введено отрицательное число, то прекращать работу цикла: sm = 0

for _ in range(10):
num = int(input())
if num < 0:
break
sm += num

print(sm)
Здесь мы в качестве перменной цикла использовали _ (нижнее подчеркивание), а не i, например. Мы могли использовать for i in range(10), но использовали for _ in range(10). В Python _ допустимое имя для переменной. По традиции нижнее подчёркивание используют для того, чтобы показать, что эта переменная нигде дальше не используется.

Если мы хотим не исполнять остальной код в блоке, то можем перескочить к следующей итерации с помощью continue. Изменим прошлый пример, мы не будем останавливать работу цикла после обнаружения, а перейдем к следующей итерации: sm = 0

for _ in range(10):
num = int(input())
if num < 0:
continue
sm += num

print(sm)

Оператор else используется, чтобы выполнить блок кода в том случае, если цикл завершился без прирываний с помощью break. Возьмём предыдущий пример c break: sm = 0

for _ in range(10):
num = int(input())
if num < 0:
break
sm += num
else:
print("Сложено все 10 чисел")

print(sm)
Вывод в блоке else произойдет, если мы не прерывали цикл из-за появления отрицательного числа.

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

Вложенный цикл расположен в еще одном цикле. Часы служат хорошим примером работы вложенного цикла. Секундная, минутная и часовая стрелки вращаются вокруг циферблата. Часовая стрелка смещается всего на 1 шаг для каждых 60 шагов минутной стрелки. И секундная стрелка должна сделать 60 шагов для 1 шага минутной стрелки. Это означает, что для каждого полного оборота часовой стрелки (12 шагов), минутная стрелка делает 720 (12 x 60) шагов, а секундная - 43200 (12 x 60 x 60) шагов.

Рассмотрим цикл, который частично моделирует электронные часы. Он показывает секунды от 0 до 59: for seconds in range(60):
print(seconds)

Можно добавить переменную minutes и вложить цикл написанный выше внутрь еще одного цикла, который повторяется 60 раз: for minutes in range(60):
for seconds in range(60):
print(minutes, ':', seconds)

Для того, чтобы сделать модель законченной, можно добавить еще одну переменную для подсчета часов: for hours in range(24):
for minutes in range(60):
for seconds in range(60):
print(hours, ':', minutes, ':', seconds)
Результатом работы такого кода будет:
0 : 0 : 0
0 : 0 : 1
0 : 0 : 2
...
23 : 59 : 58
23 : 59 : 59

Самый внутренний цикл сделает 60 итераций для каждой итерации среднего цикла. Средний цикл сделает 60 итераций для каждой итерации самого внешнего цикла. Когда самый внешний цикл сделает 24 итерации, средний сделает 24 x 60 = 1440 итераций, и самый внутренний цикл сделает 24 x 60 x 60 = 86400 итераций!

Пример имитационной модели часов подводит нас к нескольким моментам, имеющим отношение к вложенным циклам:

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

Мы можем вкладывать друг в друга циклы как for, так и while, речь о котором пойдет в следующем уроке.

Операторы break и continue во вложенных циклах

Оператор break выполняет прерывание ближайшего цикла в котором он расположен. Аналогично, оператор continue осуществляет переход на следующую итерацию ближайшего цикла.

Рассмотрим программный код: for i in range(3):
for j in range(3):
print(i, j)
Результатом его выполнения будут 9 строк:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2

Изменим код, добавив во вложенный цикл условный оператор с оператором break: for i in range(3):
for j in range(3):
if i == j:
break
print(i, j)
Результатом выполнения нового кода будут 3 строки:
1 0
2 0
2 1

Изменим оператор прерывания break на оператор continue: for i in range(3):
for j in range(3):
if i == j:
continue
print(i, j)
Результатом выполнения нового кода будут 6 строк:
0 1
0 2
1 0
1 2
2 0
2 1

Если необходимо добиться прерывания внешнего цикла из-за выполнения условия во внутреннем, то стоит сделать это через сигнальную метку (обычно такая переменная называется flag). flag = False

for i in range(3):
if flag: # то же самое, что и if flag == True:
break
for j in range(3):
if i == j:
flag = True
break
print(i, j)
В данном случае весь цикл прервется сразу же, как только переменным i и j будут присвоены значение 0.

Один интересный способ узнать о работе вложенных циклов состоит в их использовании для вывода на экран комбинаций символов. Давайте взглянем на один простой пример. Предположим, что мы хотим напечатать на экране звездочки в виде прямоугольника:
******
******
******
******
******
******
******
******

Таблица состоящая из звездочек состоит из 8 строк и 6 столбцов. Приведенный ниже фрагмент кода можно использовать для вывода одной строки звездочек: for j in range(6):
print('*', end='')
В функцию print помимо строки '*' мы через запятую передали именной аргумент end='', по умолчанию end='\n' т.е. это перевод строки, значит мы вместо перевода строки передали пустую строку, все 6 звездочек напечатаются вместе в одну строку.

Для того чтобы завершить весь вывод таблицы звездочек, нам нужно выполнить этот цикл восемь раз. Мы можем поместить этот цикл в еще один цикл, который делает восемь итераций, как показано ниже: for i in range(8):
for j in range(6):
print('*', end='')
print()

Внешний цикл делает восемь итераций. Во время каждой итерации этого цикла внутренний цикл делает 6 итераций. (Обратите внимание, что в строке 4 после того, как все строки были напечатаны, мы вызываем функцию print(). Мы должны это сделать, чтобы в конце каждой строки продвинуть экранный курсор на следующую строку. Без этой инструкции все звездочки будут напечатаны на экране в виде одной длинной строки.)

Давайте рассмотрим еще один пример. Предположим, что вы хотите напечатать звездочки в комбинации, которая похожа на приведенный ниже звездный треугольник:
*
**
***
****
*****
******
*******
********

Представим эту комбинацию звездочек, как сочетание строк и столбцов. В этой комбинации всего восемь строк. В первой строке один столбец. Во второй строке – два столбца. В третьей строке – три. И так продолжается до восьмой строки, в которой восемь столбцов. for i in range(8):
for j in range(i + 1):
print('*', end='')
print()