Retour au cours

compréhensions de listes : map/filtre en compréhension

dans cette leçon, vous passez des boucles verbeuses et de map()/filter() à des compréhensions claires : [expr for x in iterable if cond].

objectifs

  • transformer une séquence avec une compréhension
  • filtrer selon une condition
  • combiner transformation + filtre + if/else dans l’expression
  • manipuler des listes de dicts (cas “données” réaliste)
  • comparer avec map() et filter() pour comprendre les équivalents

explication détaillée

une compréhension de liste est une construction qui permet de créer une nouvelle liste en une seule expression. sa forme générale :

  • transformation seule : [expr(x) for x in data]
  • filtrage : [x for x in data if cond(x)]
  • transformation + filtre : [expr(x) for x in data if cond(x)]
  • branchement simple dans l’expression : [a if cond(x) else b for x in data]

par rapport à map()/filter() :

  • plus lisible quand la logique est courte
  • plus performant que des append dans une boucle python
  • toujours préférer la clarté : si l’expression devient longue, revenez à une boucle nommée

exemples exécutables

# transformation simple
nums = [1, 2, 3, 4]
squares = [n * n for n in nums]
print(squares)
# filtrage
evens = [n for n in range(10) if n % 2 == 0]
print(evens)
# transformation + filtre combinés
labels = [("pair" if n % 2 == 0 else "impair") for n in range(6)]
only_pairs_squared = [n*n for n in range(10) if n % 2 == 0]
print(labels)
print(only_pairs_squared)
# équivalents map/filter
nums = [1, 2, 3, 4, 5]
via_map = list(map(lambda x: x*x, nums))
via_filter = list(filter(lambda x: x % 2 == 0, nums))
via_both = list(map(lambda x: x*x, filter(lambda x: x % 2 == 0, nums)))
print(via_map, via_filter, via_both)
# données réalistes : liste de dicts
rows = [
    {"name": "ana", "score": 12},
    {"name": "bob", "score": 18},
    {"name": "chris", "score": None},
]
# extraire les noms des personnes qui ont un score non nul et >= 15
top = [r["name"].title() for r in rows if isinstance(r.get("score"), (int, float)) and r["score"] >= 15]
print(top)  # ['Bob']
# compréhension imbriquée (petit produit cartésien)
pairs = [(x, y) for x in [1, 2, 3] for y in ["a", "b"]]
print(pairs)

bonnes pratiques

  • gardez l’expression courte et lisible
  • pas d’effets de bord (évitez print() dans la compréhension)
  • préférez une boucle explicite si la logique devient complexe
  • nommez une fonction predicate() ou transform() pour clarifier si nécessaire

pièges courants

  • mettre la condition après l’expression for (l’ordre est important)
  • empiler trop de for imbriqués → lisibilité en chute
  • oublier que la compréhension crée une nouvelle liste (ne modifie pas la source)

exercices

  1. squares(n) → renvoyer [i*i for i in range(n)].
  2. extraire les mots de plus de 4 lettres d’une phrase, normalisés (strip().lower()).
  3. à partir d’une liste de dicts {"name": str, "age": int}, récupérer les name des age >= 18.
  4. aplatir [[1,2],[3],[4,5]] en une liste plate avec une compréhension imbriquée.
  5. à partir de range(1, 21), produire "fizz", "buzz", "fizzbuzz" ou le nombre selon les règles classiques (avec if ... else dans l’expression).