Les
list comprehensions et
generator expressions sont deux concepts très proches facilitant énormément la manipulation de listes et la création de générateurs simples.
Voyons tout d'abord les
list comprehensions, plus faciles à aborder que les
generator expressions que nous verrons ensuite.
Il arrive parfois que l'on doive faire le même traitement sur tous les éléments d'une liste, ou qu'on veuille éliminer tous les éléments d'une liste ne satisfaisant pas un prédicat. Pour cela, plusieurs solutions sont possibles :
- la boucle for : c'est une solution plutôt mauvaise car elle nécessite (si on veut faire quelque chose de correct) une copie de la liste ; elle ne permet pas de travailler directement sur nos éléments ;
- les méthodes map/filter et les itérateurs imap/ifilter : cette solution est clairement meilleure, du moins en termes de performances ; ces fonctions sont codées en C et travaillent directement sur les éléments de notre liste. Cependant, lorsque le traitement à réaliser n'est pas faisable par une fonction déjà créée, on doit créer cette fonction ou utiliser une fonction lambda, ralentissant ainsi l'exécution et réduisant la lisibilité ;
- les list comprehensions : elles permettent de récupérer une nouvelle liste avec tous les éléments de l'ancienne liste filtrés et sur lesquels on a effectué (ou non) un traitement. C'est à cette méthode, comme vous l'avez sûrement compris, que l'on va s'intéresser.
Une
list comprehension a la syntaxe suivante :
Code : Python1 | [expression for element in liste if predicat]
|
Le prédicat étant optionnel, la syntaxe peut donc se réduire à ceci :
Code : Python1 | [expression for element in liste]
|
expression est une expression Python (donc par exemple un tuple, une liste, une fonction, un type, une
list comprehension, ou même plus simplement une somme ou un produit

), qui peut utiliser notre variable
element. Cette
list comprehension va créer une nouvelle liste avec, à la place de
element, la valeur de
expression qui peut, bien entendu, dépendre de
element comme vous l'aurez sûrement compris.
Voyons maintenant quelques choses réalisables facilement avec les
list comprehensions :
Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | >>> liste = range(10) # On prend une liste contenant les 10 premiers entiers naturels
>>> liste
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [element + 1 for element in liste] # La même liste en ajoutant 1 à chaque élément
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [element ** 2 for element in liste] # On élève les éléments au carré
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> liste, liste == range(10) # La liste n'est pas modifiée ;)
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], True)
>>> liste = [element for element in liste if element % 2 == 0] # On prend tous les éléments pairs de notre liste
>>> liste
[0, 2, 4, 6, 8]
>>> [element ** 4 for element in liste if element < 7] # On met à la puissance 4 les éléments inférieurs à 7
[0, 16, 256, 1296]
|
Maintenant que les
list comprehensions n'ont plus de secrets pour vous, voyons leur petite soeur : les
generator expressions.
Ces expressions sont très proches des
list comprehensions ; la seule différence est que, contrairement aux
list comprehensions qui renvoient une liste, la
generator expression renvoie un générateur sur lequel on peut itérer pour récupérer les éléments calculés. Cela permet de réaliser la transformation de nos éléments à la volée quand on itére sur notre générateur.
Leur syntaxe est, elle aussi, simplissime :
Code : Python1 | (expression for element in liste)
|
On peut également, comme pour les
list comprehensions, rajouter une condition avec
if predicat au bout.
La seule vraie différence est l'utilisation de parenthèses à la place des crochets. Cela permet d'ailleurs de l'utiliser avec une légère variante syntaxique lors de l'appel d'une fonction :
Code : Python1 | fonction(expression for element in liste)
|
Un petit exemple de leur utilisation est le suivant :
Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | >>> liste = range(10)
>>> (elem - 5 for elem in liste)
<generator object at 0x7f004ec20878>
>>> gen = (elem - 5 for elem in liste)
>>> for elem in gen: print elem
...
-5
-4
-3
-2
-1
0
1
2
3
4
>>> list(elem - 5 for elem in liste) # Une autre façon d'écrire une list comprehension ;)
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
|
Utilisez les
list comprehensions et les
generator expressions le plus souvent possible quand vous réalisez des traitements simples sur les éléments d'une liste : cela simplifie énormément la lecture de votre code par rapport à une boucle.
Pour plus d'informations,
PEP 202 et
PEP 289.