Break out of nested loops in Python

Modified: | Tags: Python

This article explains how to break out of nested loops in Python.

See the following article for the basic usage of a for loop in Python.

How to write nested loops in Python

In Python, you can write nested loops (multiple loops) as follows. Since blocks are represented by indentation in Python, you can create nested loops by adding additional indentation.

l1 = [1, 2, 3]
l2 = [10, 20, 30]

for i in l1:
    for j in l2:
        print(i, j)
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# 2 30
# 3 10
# 3 20
# 3 30

When break is executed in the inner loop, it only exits from that loop, and the outer loop continues.

for i in l1:
    for j in l2:
        print(i, j)
        if i == 2 and j == 20 :
            print('BREAK')
            break
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# BREAK
# 3 10
# 3 20
# 3 30

Break out of nested loops with else and continue

In a Python for loop, you can use else and continue in addition to break.

You can break all loops with else and continue.

for i in l1:
    for j in l2:
        print(i, j)
        if i == 2 and j == 20:
            print('BREAK')
            break
    else:
        continue
    break
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# BREAK

The code with explanation is as follows.

for i in l1:
    print('Start outer loop')

    for j in l2:
        print('--', i, j)
        if i == 2 and j == 20:
            print('-- BREAK inner loop')
            break
    else:
        print('-- Finish inner loop without BREAK')
        continue

    print('BREAK outer loop')
    break
# Start outer loop
# -- 1 10
# -- 1 20
# -- 1 30
# -- Finish inner loop without BREAK
# Start outer loop
# -- 2 10
# -- 2 20
# -- BREAK inner loop
# BREAK outer loop

When the inner loop ends normally without break, continue in the else clause is executed. This continue pertains to the outer loop, moving it to the next iteration and bypassing any subsequent code in the current iteration, including break.

When the inner loop ends with break, continue in the else clause is not executed. In this case, break in the outer loop is executed, exiting the outer loop as well.

As a result, whenever the inner loop ends with break, break in the outer loop is also executed.

The same concept applies regardless of the number of nested loops. An example of a triple loop is as follows.

l1 = [1, 2, 3]
l2 = [10, 20, 30]
l3 = [100, 200, 300]

for i in l1:
    for j in l2:
        for k in l3:
            print(i, j, k)
            if i == 2 and j == 20 and k == 200:
                print('BREAK')
                break
        else:
            continue
        break
    else:
        continue
    break
# 1 10 100
# 1 10 200
# 1 10 300
# 1 20 100
# 1 20 200
# 1 20 300
# 1 30 100
# 1 30 200
# 1 30 300
# 2 10 100
# 2 10 200
# 2 10 300
# 2 20 100
# 2 20 200
# BREAK

Break out of nested loops with a flag variable

The method mentioned above, using else and continue, might be difficult to understand for those new to Python.

Introducing a flag variable can make the code more understandable to some readers.

If the inner loop ends with break, set the flag to True. In the outer loop, use the flag's value to determine whether to execute break.

Double-loop:

l1 = [1, 2, 3]
l2 = [10, 20, 30]

flag = False
for i in l1:
    for j in l2:
        print(i, j)
        if i == 2 and j == 20:
            flag = True
            print('BREAK')
            break
    if flag:
        break
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# BREAK

Triple-loop:

l1 = [1, 2, 3]
l2 = [10, 20, 30]
l3 = [100, 200, 300]

flag = False
for i in l1:
    for j in l2:
        for k in l3:
            print(i, j, k)
            if i == 2 and j == 20 and k == 200:
                flag = True
                print('BREAK')
                break
        if flag:
            break
    if flag:
        break
# 1 10 100
# 1 10 200
# 1 10 300
# 1 20 100
# 1 20 200
# 1 20 300
# 1 30 100
# 1 30 200
# 1 30 300
# 2 10 100
# 2 10 200
# 2 10 300
# 2 20 100
# 2 20 200
# BREAK

Avoid nested loops with itertools.product()

You can avoid nested loops with itertools.product().

You can use itertools.product() to achieve the same result as nested loops by generating all combinations of multiple lists in one loop.

import itertools

l1 = [1, 2, 3]
l2 = [10, 20, 30]

for i, j in itertools.product(l1, l2):
    print(i, j)
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# 2 30
# 3 10
# 3 20
# 3 30

Since it is a single loop, you can simply use break under the desired conditions.

for i, j in itertools.product(l1, l2):
    print(i, j)
    if i == 2 and j == 20:
        print('BREAK')
        break
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# BREAK

By adding arguments to itertools.product(), you can execute the process equivalent to triple loops or even more complex nested loops.

l1 = [1, 2, 3]
l2 = [10, 20, 30]
l3 = [100, 200, 300]

for i, j, k in itertools.product(l1, l2, l3):
    print(i, j, k)
    if i == 2 and j == 20 and k == 200:
        print('BREAK')
        break
# 1 10 100
# 1 10 200
# 1 10 300
# 1 20 100
# 1 20 200
# 1 20 300
# 1 30 100
# 1 30 200
# 1 30 300
# 2 10 100
# 2 10 200
# 2 10 300
# 2 20 100
# 2 20 200
# BREAK

Note

With itertools.product(), the process for each element is executed for all possible combinations.

In the example using itertools.product(), the multiplication is performed 9 times for both i and j:

for i, j in itertools.product(l1, l2):
    x = i * 2 + j * 3
    print(i, j, x)
# 1 10 32
# 1 20 62
# 1 30 92
# 2 10 34
# 2 20 64
# 2 30 94
# 3 10 36
# 3 20 66
# 3 30 96

In contrast, with nested loops, the multiplication for i occurs only based on the number of outer elements. In the following example, it's performed only 3 times:

for i in l1:
    temp = i * 2
    for j in l2:
        x = temp + j * 3
        print(i, j, x)
# 1 10 32
# 1 20 62
# 1 30 92
# 2 10 34
# 2 20 64
# 2 30 94
# 3 10 36
# 3 20 66
# 3 30 96

Speed comparison

This section shows the results of measuring the execution times for each method. The following example uses the Jupyter Notebook magic command %%timeit. Note that this will not work if run as a Python script.

Please note that the results may vary depending on the number of elements and the depth of nested for loops.

Consider a triple loop with 100 elements:

import itertools

n = 100
l1 = range(n)
l2 = range(n)
l3 = range(n)

x = n - 1

%%timeit
for i in l1:
    for j in l2:
        for k in l3:
            if i == x and j == x and k == x:
                break
        else:
            continue
        break
    else:
        continue
    break
# 43 ms ± 1.33 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
flag = False
for i in l1:
    for j in l2:
        for k in l3:
            if i == x and j == x and k == x:
                flag = True
                break
        if flag:
            break
    if flag:
        break
# 45.2 ms ± 3.42 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
for i, j, k in itertools.product(l1, l2, l3):
    if i == x and j == x and k == x:
        break
# 55.8 ms ± 458 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

The else and continue approach and the flag variable approach have similar speeds, while using itertools.product() is slower. Despite being slower, itertools.product() may improve code readability in some cases, making it a suitable choice. Consider using it based on your situation.

Related Categories

Related Articles