IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
16.3. Le filtrage de liste revisité

16.3. Le filtrage de liste revisité

Vous êtes déjà familier avec l'utilisation des list comprehensions pour le filtrage de listes. Il y a une autre manière de faire la même chose que certaines personnes trouvent plus expressive.

Python a une fonction filter prédéfinie qui prend deux arguments, une fonction et une liste et retourne une liste.[8] La fonction passée comme premier argument à filter doit elle-même prendre un argument et la liste que filter retournera contiendra tous les éléments de la liste passée en argument pour lesquels la fonction passée à filter retourne vrai.

Vous avez tout compris ? Ce n'est pas aussi difficile que ça en à l'air.

Exemple 16.7. Présentation de filter

>>> def odd(n):                 1
...     return n % 2
...     
>>> li = [1, 2, 3, 5, 9, 10, 256, -3]
>>> filter(odd, li)             2
[1, 3, 5, 9, -3]
>>> [e for e in li if odd(e)]   3
>>> filteredList = []
>>> for n in li:                4
...     if odd(n):
...         filteredList.append(n)
...     
>>> filteredList
[1, 3, 5, 9, -3]
1 odd utilise la fonction prédéfinie de modulo «%» pour retourner True si n est impair et False si n est pair.
2 filter prend deux arguments, une fonction (odd) et une liste (li). odd est appelé avec chaque élément, au fur et à mesure que la liste est parcourue. Si odd retourne une valeur vraie (rappelez-vous qu'en Python, toute valeur différente de zéro est vraie), l'élément est inclut dans la liste retournée, sinon il est filtré. Le résultat est une liste comprenant uniquement les nombres impairs de la liste originelle, dans le même ordre qu'ils apparaissaient en entrée.
3 Vous pouvez accomplir la même chose en utilisant les list comprehensions, comme vous l'avez vu à la Section 4.5, «Filtrage de listes».
4 Vous pourriez aussi accomplir la même tâche avec une boucle for. Selon vos habitudes de programmation, cela peut vous sembler plus «logique», mais les fonctions comme filter sont bien plus expressives. Non seulement elles sont plus simples à écrire, elles sont aussi plus simple à lire. Lire la boucle for est comme regarder un tableau de trop près, on voit tous les détails, mais il faut quelques secondes pour comprendre l'ensemble : «Oh, c'est juste un filtrage de liste !»

Exemple 16.8. filter dans regression.py

    files = os.listdir(path)                                1
    test = re.compile("test\.py$", re.IGNORECASE)           2
    files = filter(test.search, files)                      3
1 Comme vous l'avez vu à la Section 16.2, «Trouver le chemin», path peut contenir le chemin complet ou partiel du répertoire du script en cours d'exécution, ou une chaîne vide si le script est exécuté depuis le répertoire en cours. De toute manière, files contiendra les noms des fichiers qui sont dans le même répertoire que le script en cours d'exécution.
2 Ceci est une expression régulière compilée. Comme vous l'avez vu à la Section 15.3, «Refactorisation», si vous devez utiliser la même expression régulière de manière répétée, il vaut mieux la compiler pour obtenir de meilleures performances. L'objet compilé a une méthode search qui prend un seul argument, la chaîne à rechercher. Si l'expression régulière reconnaît la chaîne, la méthode search retourne un objet Match contenant des informations sur ce qu'elle a trouvé, sinon elle retourne None, la valeur nulle de Python.
3 Pour chaque élément de la liste files, la méthode search de l'objet expression régulière compilée test va être appelée. Si l'expression régulière reconnaît la chaîne, la méthode retourne un objet Match, que Python considère comme ayant pour valeur vrai, donc l'élément sera inclus dans la liste retournée par filter. Si l'expression régulière ne reconnaît pas la chaîne, la méthode search retourne None, ce que Python considère comme ayant pour valeur faux et donc l'élément ne sera pas inclus.

Note historique. Les versions de Python antérieures à la version 2.0 n'avaient pas de list comprehensions, donc on ne pouvait pas filtrer avec des list comprehensions; la fonction filter était la seule possibilité. Malgré l'introduction des list comprehensions dans la version 2.0, certaines personnes préfèrent encore l'ancien style avec filter (et sa fonction associée, map, que vous verrez un peu plus loin dans ce chapitre). Les deux techniques fonctionnent actuellement, le de l'une ou l'autre est donc une question de style. Il est question de ne plus supporter map et filter dans les futures versions de Python, mais aucune décision n'a été prise pour le moment.

Exemple 16.9. Filtrage avec des list comprehensions

    files = os.listdir(path)                               
    test = re.compile("test\.py$", re.IGNORECASE)          
    files = [f for f in files if test.search(f)] 1
1 On obtient exactement le même résultat qu'avec la fonction filter. Quelle est la manière la plus expressive ? À vous de le dire.

Footnotes

[8] Techniquement, le deuxième argument de filter peut être n'importe quelle séquence, y compris les listes, les tuples et les classes se comportant comme des séquences en définissant la méthode spéciale __getitem__. Si possible, filter retournera le même type de données que vous lui avez passé, donc filtrer une liste retourne une liste, mais filtrer un tuple retourne un tuple.