Break out of nested loops in 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.