🔝 Retour au Sommaire
Dans le chapitre précédent, nous avons découvert les fonctions lambda et les fonctions d'ordre supérieur. Maintenant, nous allons explorer trois fonctions d'ordre supérieur très puissantes intégrées à Python : map(), filter() et reduce().
Ces fonctions permettent de traiter des collections de données (listes, tuples, etc.) de manière élégante et concise. Elles sont au cœur de la programmation fonctionnelle en Python.
La fonction map() applique une fonction à chaque élément d'une séquence (liste, tuple, etc.) et retourne un itérateur avec les résultats transformés.
map(fonction, iterable)fonction: la fonction à appliquer à chaque élémentiterable: la séquence à traiter (liste, tuple, etc.)
Approche classique avec une boucle :
nombres = [1, 2, 3, 4, 5]
nombres_doubles = []
for nombre in nombres:
nombres_doubles.append(nombre * 2)
print(nombres_doubles) # [2, 4, 6, 8, 10]Avec map() :
nombres = [1, 2, 3, 4, 5]
nombres_doubles = list(map(lambda x: x * 2, nombres))
print(nombres_doubles) # [2, 4, 6, 8, 10]Note importante :
map()retourne un objet map (un itérateur), il faut le convertir en liste aveclist()pour voir les résultats.
# Convertir des Celsius en Fahrenheit
temperatures_celsius = [0, 10, 20, 30, 40]
celsius_vers_fahrenheit = lambda c: (c * 9/5) + 32
temperatures_fahrenheit = list(map(celsius_vers_fahrenheit, temperatures_celsius))
print(f"Celsius : {temperatures_celsius}")
print(f"Fahrenheit : {temperatures_fahrenheit}")
# Fahrenheit : [32.0, 50.0, 68.0, 86.0, 104.0]mots = ["python", "javascript", "java", "ruby"]
mots_majuscules = list(map(str.upper, mots))
print(mots_majuscules) # ['PYTHON', 'JAVASCRIPT', 'JAVA', 'RUBY']Astuce : On peut passer directement une méthode comme
str.uppersans lambda !
phrases = ["Bonjour", "Comment allez-vous ?", "Python", "Programmation"]
longueurs = list(map(len, phrases))
print(longueurs) # [7, 20, 6, 13]prenoms = ["alice", "bob", "charlie"]
# Capitaliser la première lettre
prenoms_formatte = list(map(lambda nom: nom.capitalize(), prenoms))
print(prenoms_formatte) # ['Alice', 'Bob', 'Charlie']On peut passer plusieurs listes à map(). La fonction recevra alors un élément de chaque liste :
nombres1 = [1, 2, 3, 4]
nombres2 = [10, 20, 30, 40]
# Additionner les éléments correspondants
sommes = list(map(lambda x, y: x + y, nombres1, nombres2))
print(sommes) # [11, 22, 33, 44]Autre exemple :
prenoms = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
# Créer des phrases descriptives
descriptions = list(map(
lambda nom, age: f"{nom} a {age} ans",
prenoms,
ages
))
for desc in descriptions:
print(desc)
# Alice a 25 ans
# Bob a 30 ans
# Charlie a 35 ansLa fonction filter() filtre les éléments d'une séquence en ne gardant que ceux qui satisfont une condition (retournent True).
filter(fonction_condition, iterable)fonction_condition: une fonction qui retourneTrueouFalseiterable: la séquence à filtrer
Approche classique avec une boucle :
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nombres_pairs = []
for nombre in nombres:
if nombre % 2 == 0:
nombres_pairs.append(nombre)
print(nombres_pairs) # [2, 4, 6, 8, 10]Avec filter() :
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nombres_pairs = list(filter(lambda x: x % 2 == 0, nombres))
print(nombres_pairs) # [2, 4, 6, 8, 10]nombres = [-5, 3, -2, 8, -1, 0, 7, -9]
positifs = list(filter(lambda x: x > 0, nombres))
print(positifs) # [3, 8, 7]mots = ["chat", "chien", "éléphant", "oiseau", "papillon", "rat"]
# Garder seulement les mots de plus de 5 lettres
mots_longs = list(filter(lambda mot: len(mot) > 5, mots))
print(mots_longs) # ['éléphant', 'oiseau', 'papillon']produits = [
{"nom": "Pomme", "prix": 2.5},
{"nom": "Banane", "prix": 1.8},
{"nom": "Mangue", "prix": 5.2},
{"nom": "Orange", "prix": 3.0},
]
# Produits à moins de 3€
produits_pas_chers = list(filter(lambda p: p["prix"] < 3, produits))
print("Produits à moins de 3€ :")
for p in produits_pas_chers:
print(f" - {p['nom']}: {p['prix']}€")
# Pomme: 2.5€
# Banane: 1.8€textes = ["Bonjour", "", "Python", " ", "Monde", ""]
# Supprimer les chaînes vides ou ne contenant que des espaces
textes_valides = list(filter(lambda t: t.strip() != "", textes))
print(textes_valides) # ['Bonjour', 'Python', 'Monde']def est_adulte(personne):
"""Vérifie si une personne est majeure."""
return personne["age"] >= 18
personnes = [
{"nom": "Alice", "age": 25},
{"nom": "Bob", "age": 17},
{"nom": "Charlie", "age": 30},
{"nom": "David", "age": 16},
]
adultes = list(filter(est_adulte, personnes))
print("Adultes :")
for p in adultes:
print(f" - {p['nom']} ({p['age']} ans)")
# Alice (25 ans)
# Charlie (30 ans)La fonction reduce() réduit une séquence à une seule valeur en appliquant de manière cumulative une fonction sur les éléments.
Important :
reduce()n'est pas une fonction native de Python. Elle doit être importée depuis le modulefunctools.
from functools import reduce
reduce(fonction, iterable[, valeur_initiale])fonction: une fonction qui prend 2 arguments (accumulateur, élément actuel)iterable: la séquence à réduirevaleur_initiale: (optionnel) valeur de départ pour l'accumulateur
reduce() applique la fonction de manière itérative :
- Applique la fonction aux deux premiers éléments
- Applique la fonction au résultat et au troisième élément
- Continue jusqu'à épuiser tous les éléments
Approche classique avec une boucle :
nombres = [1, 2, 3, 4, 5]
somme = 0
for nombre in nombres:
somme = somme + nombre
print(somme) # 15Avec reduce() :
from functools import reduce
nombres = [1, 2, 3, 4, 5]
somme = reduce(lambda acc, x: acc + x, nombres)
print(somme) # 15Explication du processus :
Étape 1 : 1 + 2 = 3
Étape 2 : 3 + 3 = 6
Étape 3 : 6 + 4 = 10
Étape 4 : 10 + 5 = 15
from functools import reduce
nombres = [2, 3, 4, 5]
produit = reduce(lambda acc, x: acc * x, nombres)
print(f"Produit : {produit}") # 2 * 3 * 4 * 5 = 120from functools import reduce
nombres = [45, 12, 89, 34, 67, 23]
maximum = reduce(lambda acc, x: acc if acc > x else x, nombres)
print(f"Maximum : {maximum}") # 89Note : Pour trouver le maximum, il est plus simple d'utiliser
max(nombres), mais cet exemple illustre le fonctionnement dereduce().
from functools import reduce
mots = ["Python", "est", "génial"]
phrase = reduce(lambda acc, mot: acc + " " + mot, mots)
print(phrase) # Python est génialAvec une valeur initiale :
from functools import reduce
mots = ["Python", "est", "génial"]
phrase = reduce(lambda acc, mot: acc + " " + mot, mots, "Langage:")
print(phrase) # Langage: Python est génialfrom functools import reduce
fruits = ["pomme", "banane", "pomme", "orange", "banane", "pomme"]
compteur = reduce(
lambda acc, fruit: {**acc, fruit: acc.get(fruit, 0) + 1},
fruits,
{}
)
print(compteur) # {'pomme': 3, 'banane': 2, 'orange': 1}from functools import reduce
listes = [[1, 2], [3, 4], [5, 6], [7, 8]]
liste_aplatie = reduce(lambda acc, liste: acc + liste, listes)
print(liste_aplatie) # [1, 2, 3, 4, 5, 6, 7, 8]from functools import reduce
def factorielle(n):
"""Calcule la factorielle de n."""
if n == 0 or n == 1:
return 1
return reduce(lambda acc, x: acc * x, range(1, n + 1))
print(f"5! = {factorielle(5)}") # 5! = 120
print(f"7! = {factorielle(7)}") # 7! = 5040 La vraie puissance de ces fonctions apparaît quand on les combine !
from functools import reduce
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Étape 1 : Filtrer les nombres pairs
pairs = filter(lambda x: x % 2 == 0, nombres)
# Étape 2 : Calculer le carré de chaque nombre
carres = map(lambda x: x ** 2, pairs)
# Étape 3 : Faire la somme
resultat = reduce(lambda acc, x: acc + x, carres)
print(f"Somme des carrés des pairs : {resultat}")
# 2² + 4² + 6² + 8² + 10² = 4 + 16 + 36 + 64 + 100 = 220Ou de manière plus compacte :
from functools import reduce
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
resultat = reduce(
lambda acc, x: acc + x,
map(lambda x: x ** 2,
filter(lambda x: x % 2 == 0, nombres))
)
print(f"Somme des carrés des pairs : {resultat}") # 220from functools import reduce
produits = [
{"nom": "Ordinateur", "prix": 800, "en_promo": True},
{"nom": "Souris", "prix": 25, "en_promo": False},
{"nom": "Clavier", "prix": 75, "en_promo": True},
{"nom": "Écran", "prix": 300, "en_promo": True},
{"nom": "Webcam", "prix": 50, "en_promo": False},
]
# Filtrer les produits en promotion
produits_promo = filter(lambda p: p["en_promo"], produits)
# Extraire les prix
prix = map(lambda p: p["prix"], produits_promo)
# Calculer le total
total = reduce(lambda acc, prix: acc + prix, prix, 0)
print(f"Prix total des produits en promotion : {total}€") # 1175€from functools import reduce
notes = [8, 15, 12, 9, 18, 14, 7, 16, 11]
# Filtrer les notes > 10
notes_valides = list(filter(lambda x: x > 10, notes))
# Calculer la somme
somme = reduce(lambda acc, x: acc + x, notes_valides)
# Calculer la moyenne
moyenne = somme / len(notes_valides)
print(f"Notes > 10 : {notes_valides}")
print(f"Moyenne : {moyenne:.2f}") # Moyenne : 14.33 Python offre aussi les compréhensions de listes qui peuvent remplacer map() et filter() de manière plus pythonique.
nombres = [1, 2, 3, 4, 5]
# Avec map()
doubles_map = list(map(lambda x: x * 2, nombres))
# Avec compréhension de liste
doubles_comp = [x * 2 for x in nombres]
print(doubles_map) # [2, 4, 6, 8, 10]
print(doubles_comp) # [2, 4, 6, 8, 10] nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Avec filter()
pairs_filter = list(filter(lambda x: x % 2 == 0, nombres))
# Avec compréhension de liste
pairs_comp = [x for x in nombres if x % 2 == 0]
print(pairs_filter) # [2, 4, 6, 8, 10]
print(pairs_comp) # [2, 4, 6, 8, 10] nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Avec map() et filter()
resultat_func = list(map(
lambda x: x ** 2,
filter(lambda x: x % 2 == 0, nombres)
))
# Avec compréhension de liste
resultat_comp = [x ** 2 for x in nombres if x % 2 == 0]
print(resultat_func) # [4, 16, 36, 64, 100]
print(resultat_comp) # [4, 16, 36, 64, 100] Utilisez les compréhensions de listes quand :
- ✅ L'opération est simple et lisible
- ✅ Vous travaillez avec une seule séquence
- ✅ Vous voulez un code plus "pythonique"
Utilisez map()/filter() quand :
- ✅ Vous avez déjà une fonction définie
- ✅ Vous travaillez avec plusieurs séquences en parallèle
- ✅ Vous voulez un style plus fonctionnel
Utilisez reduce() quand :
- ✅ Vous devez agréger/réduire une séquence à une valeur
- ✅ Il n'y a pas d'alternative plus simple (comme
sum(),max(), etc.)
from functools import reduce
# Données brutes
ventes = [
{"produit": "Laptop", "quantite": 2, "prix_unitaire": 800},
{"produit": "Souris", "quantite": 5, "prix_unitaire": 25},
{"produit": "Clavier", "quantite": 3, "prix_unitaire": 75},
{"produit": "Écran", "quantite": 1, "prix_unitaire": 300},
]
# Pipeline de traitement
def traiter_ventes(ventes):
# 1. Calculer le montant total de chaque vente
avec_montants = list(map(
lambda v: {**v, "montant_total": v["quantite"] * v["prix_unitaire"]},
ventes
))
# 2. Filtrer les ventes de plus de 200€
ventes_importantes = list(filter(
lambda v: v["montant_total"] > 200,
avec_montants
))
# 3. Calculer le chiffre d'affaires total
ca_total = reduce(
lambda acc, v: acc + v["montant_total"],
ventes_importantes,
0
)
return ventes_importantes, ca_total
ventes_importantes, ca = traiter_ventes(ventes)
print("Ventes importantes (>200€) :")
for v in ventes_importantes:
print(f" {v['produit']}: {v['montant_total']}€")
print(f"\nChiffre d'affaires : {ca}€")# Données d'étudiants
etudiants = [
{"nom": "Alice", "notes": [15, 18, 16]},
{"nom": "Bob", "notes": [12, 14, 13]},
{"nom": "Charlie", "notes": [17, 19, 18]},
]
# Calculer la moyenne de chaque étudiant
etudiants_avec_moyennes = list(map(
lambda e: {
"nom": e["nom"],
"notes": e["notes"],
"moyenne": sum(e["notes"]) / len(e["notes"])
},
etudiants
))
# Filtrer ceux qui ont la moyenne >= 15
mentions_bien = list(filter(
lambda e: e["moyenne"] >= 15,
etudiants_avec_moyennes
))
print("Étudiants avec mention Bien (>=15) :")
for e in mentions_bien:
print(f" {e['nom']}: {e['moyenne']:.2f}")from functools import reduce
texte = "Python est un langage de programmation puissant et facile à apprendre"
# Compter le nombre total de caractères (sans espaces)
mots = texte.split()
# Extraire la longueur de chaque mot
longueurs = list(map(len, mots))
# Calculer la longueur totale
longueur_totale = reduce(lambda acc, x: acc + x, longueurs)
# Calculer la longueur moyenne
longueur_moyenne = longueur_totale / len(mots)
print(f"Nombre de mots : {len(mots)}")
print(f"Longueur totale : {longueur_totale} caractères")
print(f"Longueur moyenne : {longueur_moyenne:.2f} caractères/mot") map() et filter() retournent des itérateurs, pas des listes. Cela signifie que les calculs ne sont effectués que lorsque nécessaire.
nombres = range(1, 1000000) # 1 million de nombres
# Ceci est instantané (pas de calcul)
doubles = map(lambda x: x * 2, nombres)
# Le calcul n'a lieu que quand on convertit en liste
# liste_doubles = list(doubles) # Ceci prendrait du tempsnombres = [1, 2, 3, 4, 5]
# ❌ Pas besoin de list() si on itère une seule fois
for n in map(lambda x: x * 2, nombres):
print(n)
# ✅ Utilisez list() si vous devez :
# - Réutiliser le résultat
# - Accéder à des éléments spécifiques
# - Connaître la longueur
doubles = list(map(lambda x: x * 2, nombres))
print(len(doubles)) # Nécessite une liste
print(doubles[2]) # Nécessite une liste Python propose des alternatives souvent plus simples pour certains cas :
from functools import reduce
nombres = [1, 2, 3, 4, 5]
# Avec reduce()
somme_reduce = reduce(lambda acc, x: acc + x, nombres)
# Plus simple et plus rapide
somme_native = sum(nombres)
print(somme_reduce) # 15
print(somme_native) # 15 from functools import reduce
nombres = [45, 12, 89, 34, 67]
# Avec reduce()
max_reduce = reduce(lambda acc, x: acc if acc > x else x, nombres)
# Plus simple et plus rapide
max_native = max(nombres)
print(max_reduce) # 89
print(max_native) # 89 nombres = [2, 4, 6, 8, 10]
# Vérifier si tous les nombres sont pairs
tous_pairs = all(map(lambda x: x % 2 == 0, nombres))
# Ou plus simple avec compréhension
tous_pairs = all(x % 2 == 0 for x in nombres)
print(tous_pairs) # True# ❌ Difficile à lire
resultat = list(map(lambda x: x * 2, filter(lambda x: x % 2 == 0, map(lambda x: x + 1, range(10)))))
# ✅ Plus clair avec des étapes
nombres = range(10)
increments = map(lambda x: x + 1, nombres)
pairs = filter(lambda x: x % 2 == 0, increments)
doubles = map(lambda x: x * 2, pairs)
resultat = list(doubles)
# ✅✅ Encore mieux avec compréhension
resultat = [2 * (x + 1) for x in range(10) if (x + 1) % 2 == 0]def calculer_montant_tva(prix, taux_tva=0.20):
"""Calcule le montant TTC."""
return prix * (1 + taux_tva)
prix_ht = [100, 200, 150, 300]
# ✅ Clair et réutilisable
prix_ttc = list(map(calculer_montant_tva, prix_ht))
# ❌ Moins clair avec lambda
prix_ttc = list(map(lambda p: p * 1.20, prix_ht))nombres = [1, 2, 3, 4, 5]
# ❌ Compliqué avec reduce()
from functools import reduce
somme = reduce(lambda acc, x: acc + x, nombres)
# ✅ Simple et clair
somme = sum(nombres)nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Avec map/filter (style fonctionnel)
resultat = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, nombres)))
# Avec compréhension (style pythonique)
resultat = [x ** 2 for x in nombres if x % 2 == 0]
# Les deux sont corrects, choisissez selon votre préférenceDans ce chapitre, nous avons exploré trois fonctions fondamentales de la programmation fonctionnelle :
- Objectif : Transformer chaque élément d'une séquence
- Syntaxe :
map(fonction, iterable) - Retourne : Un itérateur (convertir avec
list()si nécessaire) - Usage : Appliquer une même opération à tous les éléments
- Objectif : Filtrer les éléments selon une condition
- Syntaxe :
filter(fonction_condition, iterable) - Retourne : Un itérateur avec les éléments qui satisfont la condition
- Usage : Sélectionner certains éléments d'une séquence
- Objectif : Réduire une séquence à une seule valeur
- Syntaxe :
reduce(fonction, iterable[, valeur_initiale]) - Import :
from functools import reduce - Usage : Agréger, accumuler, combiner des éléments
✅ Ces fonctions permettent un style de programmation fonctionnel
✅ Elles peuvent être combinées pour créer des pipelines de traitement
✅ Les compréhensions de listes sont souvent plus pythoniques
✅ Privilégiez toujours la lisibilité du code
✅ Utilisez les alternatives natives quand elles existent (sum(), max(), etc.)
- map() : Transformation de données, conversion de formats
- filter() : Sélection, validation, nettoyage de données
- reduce() : Agrégation, calculs cumulatifs (avec parcimonie)
Dans le prochain chapitre, nous explorerons les décorateurs avancés, une autre facette puissante de la programmation fonctionnelle en Python !