2.12. Boucles

Une boucle exécute le même bloc de code de façon répétée. Python en propose deux formes : while, qui continue tant qu’une condition reste vraie, et for, qui parcourt les éléments d’une séquence.

Organigrammes côte à côte. while : tester la condition, exécuter le corps si elle est vraie, recommencer. for : prendre l'élément suivant de l'itérable, exécuter le corps, recommencer jusqu'à épuisement.

while continue de tester une condition ; for parcourt une séquence jusqu’à son épuisement.

2.12.1. Boucles while

Une boucle while teste sa condition avant chaque itération et exécute le corps jusqu’à ce que le test devienne faux :

count = 0
while count < 5:
    print(count)
    count += 1

Sortie

0
1
2
3
4

Si la condition est vraie au départ et ne devient jamais fausse, la boucle s’exécute indéfiniment. while True: est l’idiome standard pour une boucle principale, quittée explicitement avec break :

while True:
    step()
    if done():
        break

2.12.2. Boucles for

Une boucle for parcourt les éléments d’un itérable – une liste, un tuple, une chaîne, des bytes, un dict, ou tout autre objet qui prend en charge l’itération :

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

Sortie

apple
banana
cherry

La même forme fonctionne sur une chaîne, où chaque élément est une chaîne d’un seul caractère :

for letter in "OpenMV":
    print(letter)

Sortie

O
p
e
n
M
V

Itérer directement un dict produit ses clés, dans l’ordre d’insertion :

for key in {"a": 1, "b": 2}:
    print(key)

Sortie

a
b

Chaque passage lie la variable de boucle (fruit, letter, key) à l’élément suivant. Après la fin de la boucle, la variable conserve la valeur de la dernière itération.

2.12.3. range

Pour les boucles sur une plage numérique, utilisez range() :

  • range(stop) – 0, 1, …, stop - 1.

  • range(start, stop) – start, start + 1, …, stop - 1.

  • range(start, stop, step) – avec un pas personnalisé (les valeurs négatives comptent à rebours).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() produit les valeurs paresseusement – il ne construit pas de liste en mémoire. Pour obtenir une véritable list, encadrez-le : list(range(10)).

2.12.4. enumerate

Lorsque la boucle a besoin à la fois de l’indice et de l’élément, enumerate() produit des paires (index, item) :

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

Démarrez l’indice à une autre valeur que zéro en passant un second argument : enumerate(items, start=1).

2.12.5. zip

Pour parcourir deux itérables (ou plus) en parallèle, utilisez zip(). Il produit un tuple par position et s’arrête à l’entrée la plus courte :

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

Sortie

alice 88
bob 92
carol 70

2.12.6. Affectation en ligne avec :=

L’opérateur morse := est une affectation qui est aussi une expression. Il lie un nom et s’évalue à cette même valeur, simultanément. Dans une boucle while, cela condense le motif courant « lire, vérifier, corps » en une seule ligne :

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

Les deux formes font la même chose. Optez pour := lorsque la duplication de l’affectation nuit véritablement à la lisibilité ; n’y recourez pas uniquement pour faire malin. Les parenthèses sont requises dans la plupart des positions pour lever toute ambiguïté de l’expression.