Python

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

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

Главная идея простая: внешний цикл выбирает крупный элемент, внутренний проходит по элементам внутри него

Первый пример со списком списков

rows = [
    [1, 2, 3],
    [4, 5, 6],
]

for row in rows:
    for value in row:
        print(value)

Вывод:

1
2
3
4
5
6

Сначала внешний цикл берет строку [1, 2, 3], затем внутренний цикл печатает каждое число внутри этой строки. Потом внешний цикл переходит к [4, 5, 6], и внутренний цикл снова проходит по значениям

Внешний и внутренний цикл

Вложенные циклы легче читать, если дать переменным честные имена

table = [
    ['Анна', 5, 4],
    ['Олег', 3, 5],
]

for student in table:
    for value in student:
        print(value)

student — одна строка таблицы

value — отдельная ячейка внутри этой строки

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

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

Классический пример вложенных циклов — таблица умножения

for x in range(1, 4):
    for y in range(1, 4):
        print(f'{x} x {y} = {x * y}')

Вывод:

1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9

Внешний цикл отвечает за первое число, внутренний — за второе. На каждой паре Python выполняет тело внутреннего цикла

По этой теме полезно отдельно посмотреть Составьте еженедельное расписание занятий, чтобы расширить контекст и сравнить подходы

По этой теме полезно отдельно посмотреть Аннотации типов для декораторов в Python, чтобы расширить контекст и сравнить подходы

Координаты поля

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

for row in range(3):
    for col in range(3):
        print(f'строка {row}, колонка {col}')

Так можно пройти по клеткам поля 3 на 3

Если нужно вывести поле, а не каждую координату с новой строки:

for row in range(3):
    line = ''

    for col in range(3):
        line += f'({row},{col}) '

    print(line)

Внутренний цикл собирает одну строку, а внешний печатает ее после заполнения

Сумма чисел в таблице

Практический пример: посчитать сумму всех значений в списке списков

orders = [
    [1200, 800, 500],
    [300, 700],
    [1500],
]

total = 0

for day in orders:
    for amount in day:
        total += amount

print(total)

Здесь внешний цикл идет по дням, внутренний — по заказам внутри дня

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

Сравнение всех пар

Иногда нужно сравнить каждый элемент одного списка с каждым элементом другого

names = ['Анна', 'Олег']
skills = ['Python', 'SQL', 'Git']

for name in names:
    for skill in skills:
        print(f'{name} изучает {skill}')

Это даст все сочетания имени и навыка

Но будьте осторожны: если в первом списке 1000 элементов, а во втором 1000, получится миллион операций

break во вложенном цикле

break прерывает только тот цикл, внутри которого находится

table = [
    [1, 2, 3],
    [4, 0, 6],
    [7, 8, 9],
]

for row in table:
    for value in row:
        if value == 0:
            print('найден ноль')
            break

В этом примере break остановит внутренний цикл, но внешний продолжит следующую строку

Если нужно полностью прекратить поиск, часто используют флаг

found = False

for row in table:
    for value in row:
        if value == 0:
            found = True
            break

    if found:
        break

print(found)

Когда вложенный цикл лучше заменить

Вложенный цикл не ошибка, но иногда есть более понятный инструмент

Для списка списков можно использовать sum

rows = [[1, 2], [3, 4]]
total = sum(sum(row) for row in rows)
print(total)

Для поиска общих элементов двух списков часто лучше взять множества

a = ['python', 'sql', 'git']
b = ['html', 'git', 'css']

common = set(a) & set(b)
print(common)

Такой вариант короче и быстрее на больших данных

Частые ошибки

  • путать внешний и внутренний цикл
  • использовать одинаковые имена переменных
  • ставить print() не на тот уровень отступа
  • ожидать, что break остановит сразу оба цикла
  • делать вложенный цикл на больших списках без оценки количества операций
  • решать через вложенный цикл задачу, где проще использовать словарь или множество

Практика

Сделайте три задачи

  1. Выведите координаты поля 4 на 4
  2. Посчитайте сумму всех чисел в списке списков
  3. Найдите общие элементы двух списков сначала вложенным циклом, а потом через set

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

Что читать дальше

Если нужно повторить обычный цикл без вложенности, начните с материала Цикл for в Python

Для остановки циклов и пропуска итераций пригодится разбор Break и continue в Python

Вложенные циклы в Python нужны для данных с двумя уровнями: строка и ячейка, список и элемент, координата row и координата col

Читайте их сверху вниз: внешний цикл выбирает контейнер, внутренний работает с содержимым

Если циклы становятся слишком тяжелыми или плохо читаются, проверьте, не подходит ли вместо них словарь, множество, генератор или отдельная функция

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x