2.30. Compréhensions¶
Une compréhension construit une nouvelle liste, un nouvel ensemble, un nouveau dictionnaire ou un nouveau générateur à partir d’un itérable existant, en une seule expression. C’est un remplacement du schéma courant consistant à partir d’un conteneur vide et à y ajouter des éléments dans une boucle.
2.30.1. Compréhensions de liste¶
squares = [x * x for x in range(5)]
print(squares)
Sortie
[0, 1, 4, 9, 16]
La même boucle écrite explicitement :
squares = []
for x in range(5):
squares.append(x * x)
La forme par compréhension est une expression unique qui construit la liste directement. Il n’y a pas de squares = [] ni de .append – le résultat est la valeur de la compréhension.
L’expression de tête produit chaque élément ; la clause for nomme la variable de boucle ; une clause if facultative filtre les éléments.¶
2.30.2. Filtrer avec if¶
Une clause if facultative ne conserve que les éléments correspondants :
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
Sortie
[0, 2, 4, 6, 8]
Le filtre s’exécute avant l’expression de tête – x % 2 == 0 est vérifié en premier ; seules les valeurs correspondantes atteignent x pour la sortie.
2.30.3. Compréhensions de dictionnaire et d’ensemble¶
La même forme fonctionne avec les littéraux de dictionnaire et d’ensemble.
Une compréhension de dictionnaire comporte une paire key: value avant le for :
squares = {x: x * x for x in range(5)}
print(squares)
Sortie
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Une compréhension d’ensemble utilise des accolades et une expression unique :
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
Sortie
{1, 2}
2.30.4. Expressions génératrices¶
Les parenthèses produisent une expression génératrice au lieu d’une liste. Les valeurs sont calculées une à une, à la demande :
total = sum(x * x for x in range(1000))
Aucune liste d’un million d’éléments n’est jamais construite. Les valeurs s’écoulent une par une vers sum(), qui les additionne et écarte chacune au fur et à mesure.
Les expressions génératrices sont le bon choix pour alimenter des valeurs dans une fonction de réduction (sum(), max(), any(), all()) ou tout autre code consommant un itérateur – elles économisent la mémoire qu’aurait utilisée la liste équivalente.
2.30.5. Quand ne pas utiliser de compréhension¶
Les compréhensions sont concises mais pas toujours plus claires. Optez pour une simple boucle for quand :
Le corps a besoin de plus d’une instruction (une compréhension n’accepte qu’une seule expression).
Le corps a des effets de bord (afficher, écrire dans un fichier) – les compréhensions servent à construire une collection, pas à exécuter des actions.
Le filtre ou la transformation comporte tant de parties que la compréhension ne se lit plus de gauche à droite.