Python et la compréhension de liste : exemples

Python 3000, la prochaine version de Python, va supprimer un certain nombre de primitives pourtant bien utiles, tels que map() et filter(). A la place, la solution recommandée est l’utilisation des “list comprehension”, où en francais, compréhension de liste. Wikipedia nous propose cette définition :

Une liste, comme un ensemble, peut-être définie par la donnée d’une propriété caractéristique de ses éléments, on dit qu’on l’a définie en compréhension. Comme cette construction offre des avantages de lisibilité et de concision, certains langages de programmation proposent donc la possibilité de définir une liste par une propriété caractéristique et l’on appelle cela la compréhension de liste.

Avant de débuter avec les exemples, voici la grammaire des compréhension de liste en Python telle qu’elle est donnée dans la documentation :

test 	 	::=  	and_test ( "or" and_test )* | lambda_form
testlist 	::= 	test ( "," test )* [ "," ]
list_display 	::= 	"[" [listmaker] "]"
listmaker 	::= 	expression ( list_for | ( "," expression )* [","] )
list_iter 	::= 	list_for | list_if
list_for 	::= 	"for" expression_list "in" testlist [list_iter]
list_if 	::= 	"if" test [list_iter]

Exemple 1 : équivalence à map :

Trouver les 10 premières puissances de 2, avec map :

map(lambda x: 2**x, xrange(10))

Avec la compréhension de listes :

[2**x for x in xrange(10)]

Exemple 2 : équivalence à filter :

Trouver les nombres pairs parmis les nombres de 0 à 9, avec filter() :

filter(lambda x:x%2 == 0, xrange(10))

Avec la compréhension de listes :

[x for x in xrange(10) if x%2==0]

Exemple 3 : les deux à la fois :

Trouver la puissance de deux des nombres pairs de 0 à 9 (oui c’est totalement inutile), avec map() et filter() :

map(lambda x:2**x, filter(lambda x:x%2==0, xrange(10)))

Et avec les compréhension de listes :

[2**x for x in xrange(10) if x%2==0]

Un peu plus compréhensible non ?

Exemple 4 : Renvoyer plusieurs résultats

On reprend l’exemple des puissances de deux, mais on veut renvoyer cette fois ci, à la fois le nombre calculé, et sa puissance :

[(x, 2**x) for x in xrange(10)]

Et avec un for pour gérer l’affichage :

for n, v in [(x, 2**x) for x in xrange(10)]:
     print "2^%s = %s" % (n, v)

Résultat :

2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512

Pratique !

Le Samedi 26 janvier 2008 à 18h38 Developpement Tags : ,

Commentaires RSS feed

Avatar de l'auteur

commentaire de BatchyX

janvier 26th, 2008 at 7:11

à noter que les list comprehensions balancent directement des listes.

si on veut juste un iterateur (comme dans le dernier exemple), on peut utiliser des ”iterator comprehension” :
((x, 2**x) for x in xrange(10))

à noter que l’iterator comprehension est plus recent que les list comprehension, qui marchent depuis euh, avant python 2.2 …

Avatar de l'auteur

commentaire de BatchyX

janvier 26th, 2008 at 7:17

Et un truc chiant avec la compréhension de liste c’est l’ordre d’évaluation quand on en a plusieurs :

>> [ x for y in xrange(5) for x in xrange(y)]
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]

pas du tout l’ordre auquel on s’attend ;)

Avatar de l'auteur

commentaire de Antoine

http://inaps.org
janvier 27th, 2008 at 12:32

si on veut juste un iterateur (comme dans le dernier exemple), on peut utiliser des ”iterator comprehension”

Oui, d’ailleurs j’en parle ici. :)

Avatar de l'auteur

commentaire de I, NaPs » Les itérateurs et générateurs en Python

http://inaps.org/journal/les-iterateurs-et-generateurs-en-python
janvier 27th, 2008 at 12:34

[…] de manière plus concise avec les “generator expressions” (voir mon billet sur la compréhension de liste pour voir des exemples de la syntaxe générale, le seul différence résidant dans […]

Poster un commentaire


Ne sera pas publiée, elle est utile pour les Gravatars et la modération des commentaires.


Facultatif.


Vous pouvez utiliser ces marqueurs : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>