Skip to content

Sortir des boucles imbriquées en Python

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.