Boucles et itération
Une boucle for traite une à une les valeurs d’un itérable, c’est-à-dire un objet qui fournit des valeurs à parcourir, comme une liste ou un fichier ouvert. Dans le premier exemple, enumerate(values) fournit un indice et une valeur à chaque itération. Dans le second, zip associe les valeurs de deux entrées ; strict=True signale des longueurs différentes au lieu de s’arrêter silencieusement à l’entrée la plus courte. process et compare représentent les opérations à effectuer sur chaque élément ou chaque paire.
for index, value in enumerate(values):
process(index, value)
for left, right in zip(left_values, right_values, strict=True):
compare(left, right)
Utilisez range(start, stop, step) lorsque les nombres définissent eux-mêmes l'itération, et non pour imiter un indexage.
Boucles while
Une boucle while se répète tant que sa condition reste vraie. Rendez visibles l'initialisation, la progression et la terminaison :
attempts = 0
while attempts < maximum_attempts:
if try_operation():
break
attempts += 1
else:
raise RuntimeError("operation never succeeded")
Le else de la boucle ne s'exécute que si elle se termine sans break. Il est utile lorsqu'une recherche est épuisée, mais une fonction auxiliaire avec un return anticipé peut être plus claire.
Instructions de contrôle
breakquitte la boucle la plus proche.continuecommence son itération suivante.passn'effectue aucune opération ; il sert de substitut syntaxique.
Évitez les break profondément imbriqués ; extrayez une fonction ou conservez un état explicite lorsque plusieurs boucles doivent se terminer ensemble.
Mutation pendant l'itération
Changer la taille ou la structure du conteneur parcouru peut omettre des valeurs, répéter du travail ou lever une erreur. Parcourez une copie, construisez une nouvelle collection ou séparez la découverte de la mutation :
active = [item for item in items if item.enabled]
Les itérateurs sont consommables
De nombreux itérateurs ne produisent chaque valeur qu'une fois. La conversion en liste permet plusieurs parcours, mais matérialise toutes les valeurs. Conservez le traitement en flux lorsque l'entrée peut être grande.
Bornes, épuisement et entrées appariées
Le tutoriel sur l'itération
utilise un intervalle semi-ouvert : range exclut stop, commence par défaut à
zéro avec un pas de un, et refuse un pas nul avec ValueError. Un pas orienté
à l'opposé de stop produit une plage vide. Une plage stocke ses bornes sans
matérialiser tous ses entiers.
assert list(range(3)) == [0, 1, 2]
assert list(range(5, 0, -2)) == [5, 3, 1]
assert list(range(0, 5, -1)) == []
values = [10, 20]
it = iter(values)
assert next(it) == 10
assert list(it) == [20]
assert list(it) == []
assert list(values) == [10, 20]
assert list(enumerate(values, start=1)) == [(1, 10), (2, 20)]
Un itérable fournit un itérateur via iter ; celui-ci fournit des valeurs via
next jusqu'à StopIteration. Une liste fournit un nouvel itérateur à chaque
parcours, mais un itérateur épuisé reste épuisé. for gère StopIteration pour
vous. Sans strict=True, zip s'arrête à l'entrée la plus courte ; avec cette
option, des longueurs différentes lèvent ValueError pendant la consommation,
éventuellement après le traitement de certaines paires.
Le else s'exécute aussi pour une entrée vide ou une condition while initialement
fausse. Il ne s'exécute pas si return ou une exception quitte la boucle.
Dans un while, continue reteste la condition : sauter la mise à jour qui
assure la progression peut donc produire une boucle infinie.