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.