
Cet article décrit comment sortir des boucles imbriquées en Python.
- Comment écrire des boucles imbriquées en Python
- Sortir des boucles imbriquées avec else et continuer
- Sortir des boucles imbriquées avec une variable drapeau
- Évitez les boucles imbriquées avec itertools.product()
- Comparaison de vitesse
Consultez l’article suivant pour l’utilisation de base de la boucle for en Python.
Comment écrire des boucles imbriquées en Python
En Python, les boucles imbriquées (boucles multiples) sont écrites comme suit. Les blocs sont représentés par des retraits en Python, il suffit donc d’ajouter plus de retraits.
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
Lorsque break est exécuté dans la boucle interne, il ne sort que de la boucle interne et la boucle externe continue.
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
Sortir des boucles imbriquées avec else et continuer
Dans la boucle for de Python, vous pouvez utiliser else et continuer en plus de break.
Vous pouvez rompre toutes les boucles avec else et continuer.
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
Le code avec explication est le suivant.
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
Lorsque la boucle interne se termine normalement sans interruption, continue dans la clause else est exécutée. Ce continue est pour la boucle externe, et saute la pause dans la boucle externe et continue au cycle suivant.
Lorsque la boucle interne se termine par break, continue dans la clause else n’est pas exécutée. Dans ce cas, une rupture dans la boucle externe est exécutée.
Par conséquent, chaque fois que la boucle interne se termine par un break, un break dans la boucle externe est également exécuté.
L’idée est la même même si le nombre de boucles augmente. Un exemple de boucle triple est le suivant.
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
Sortir des boucles imbriquées avec une variable drapeau
La manière ci-dessus d’utiliser else et continue peut être difficile à comprendre pour ceux qui ne connaissent pas Python.
L’ajout d’une variable d’indicateur peut rendre le code plus facile à comprendre pour beaucoup.
Dans la condition où la boucle interne se termine par break, définissez l’indicateur sur True, et dans la boucle externe, définissez break en fonction de l’indicateur.
Double boucle:
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 boucle :
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
Vous pouvez éviter les boucles imbriquées avec itertools.product().
Vous pouvez utiliser itertools.product() pour obtenir toutes les combinaisons de plusieurs listes dans une boucle et obtenir le même résultat que les boucles imbriquées.
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
Puisqu’il s’agit d’une seule boucle, vous pouvez simplement casser dans les conditions souhaitées.
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
En ajoutant l’argument de itertools.product(), vous pouvez exécuter le processus correspondant à plusieurs boucles multiples.
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
Noter
Dans itertools.product(), le processus de l’élément est toujours exécuté pour toutes les combinaisons.
Dans l’exemple suivant, la multiplication est effectuée 9 fois pour i et 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
Dans le cas de boucles imbriquées, le processus de la boucle externe est exécuté par le nombre d’éléments externes.
Dans l’exemple suivant, la multiplication de la variable i n’est que de 3 fois.
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
Comparaison de vitesse
Le résultat de la mesure du temps d’exécution de chaque chemin avec la commande magique %%timeit de Jupyter Notebook est affiché. Notez qu’il ne peut pas être mesuré s’il est exécuté en tant que code Python.
Veuillez noter que les résultats seront différents selon le nombre d’éléments et le nombre de boucles for à imbriquer.
Prenons l’exemple d’une triple boucle avec 100 éléments.
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)
Utiliser else, continuer et ajouter des variables d’indicateur sont à peu près équivalents, et itertools.product() est lent.
Cependant, dans certains cas, itertools.product() est plus adapté car il améliore la lisibilité du code même s’il est lent. Vous devez l’utiliser en fonction de la situation.