Урок 21 Вложенные циклы

Циклы внутри циклов

⏱ ~10 мин чтения· 📘 Базовый

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

Цикл внутри другого цикла — внешний и внутренний:

for i in range(3):
    for j in range(2):
        print(f"i={i}, j={j}")

# Вывод:
# i=0, j=0
# i=0, j=1
# i=1, j=0
# i=1, j=1
# i=2, j=0
# i=2, j=1

Таблица умножения

Классический пример вложенных циклов:

for i in range(1, 10):
    for j in range(1, 10):
        print(f"{i}*{j}={i*j:2}", end="  ")
    print()  # новая строка

break и continue во вложенных циклах

break/continue действуют только на ближайший цикл:

for i in range(3):
    for j in range(3):
        if j == 1:
            break  # прерывает только внутренний цикл
        print(f"({i},{j})", end=" ")
    print()

# Вывод:
# (0,0)
# (1,0)
# (2,0)

Внутренний цикл зависит от внешнего

Количество итераций внутреннего цикла может зависеть от переменной внешнего цикла:

for i in range(4):
    for j in range(i):      # внутренний цикл зависит от i
        print("*", end="")
    print()                 # новая строка

# Вывод:
#
# *
# **
# ***

При i = 0 внутренний цикл не выполняется ни разу (range(0) пуст), при i = 1 — один раз и так далее. Всего будет напечатано 0 + 1 + 2 + 3 = 6 звёздочек.

Сетка координат

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

for i in range(3):
    for j in range(3):
        print(f"({i},{j})", end=" ")
    print()

# Вывод:
# (0,0) (0,1) (0,2)
# (1,0) (1,1) (1,2)
# (2,0) (2,1) (2,2)

Узор с диагональю

Выведем узор: единицы на главной диагонали (i == j), нули в остальных клетках:

for i in range(3):
    for j in range(3):
        if i == j:
            print(1, end=" ")
        else:
            print(0, end=" ")
    print()

# Вывод:
# 1 0 0
# 0 1 0
# 0 0 1

Как выйти сразу из всех вложенных циклов

break завершает только ближайший цикл. Чтобы выйти сразу из всех циклов, используют флаг — переменную-индикатор: ставим её в True во внутреннем цикле и проверяем в условии внешнего:

found = False
for i in range(5):
    for j in range(5):
        if i * j == 12:
            print(f"Нашли: {i} × {j} = 12")
            found = True
            break       # выходим из внутреннего цикла
    if found:
        break           # выходим и из внешнего

# Вывод: Нашли: 3 × 4 = 12

Сложность вложенных циклов

Если внешний цикл выполняется N раз, а внутренний — M раз, то тело внутреннего цикла выполняется N × M раз. Такую зависимость обозначают O(N × M). Если N = M, то есть оба цикла по N итераций, используют обозначение O(N²):

for i in range(100):      # N = 100
    for j in range(100):  # M = 100
        pass              # всего 100 × 100 = 10 000 итераций

Пирамидка из чисел

Соберём строку внутри цикла и выведем её. str(j) превращает число в строку, а strip() убирает лишний пробел в конце:

for i in range(1, 4):
    row = ""
    for j in range(1, i + 1):
        row += str(j) + " "
    print(row.strip())

# Вывод:
# 1
# 1 2
# 1 2 3