COURS 16 PYTHON

Cours Python : Les fonctions Lambda (fonctions anonymes)

? Objectif du cours : Maîtriser les fonctions lambda en Python, ces fonctions "express" qui permettent d'écrire du code plus concis et élégant.

Partie 1 : Introduction aux fonctions Lambda

1.1 Qu'est-ce qu'une fonction lambda ?

Une fonction lambda est une fonction anonyme (sans nom) définie sur une seule ligne. C'est comme une fonction classique, mais en version "express" !

? Analogie :
  • Fonction classique = Un repas préparé avec une recette détaillée (plus long à écrire)
  • Fonction lambda = Un pain avec chocolat  préparé rapidement (simple et efficace pour les petites tâches)

Tableau comparatif : Fonction classique vs Lambda

Caractéristique Fonction classique (def) Fonction lambda
Syntaxe def nom(params): return résultat lambda params: résultat
Nom A un nom (obligatoire) Anonyme (pas de nom)
Longueur Plusieurs lignes possibles Une seule ligne obligatoire
Complexité Peut contenir des boucles, conditions complexes Expression simple uniquement
Usage typique Fonctions réutilisables complexes Fonctions jetables pour filter, map, sort

1.2 Syntaxe de base

? Exemple 1 : Premières lambdas
# Syntaxe générale : lambda paramètres: expression

# Lambda à 1 paramètre
carre = lambda x: x ** 2
print(carre(5))                    # 25

# Lambda à 2 paramètres
addition = lambda a, b: a + b
print(addition(10, 5))              # 15

# Lambda à 3 paramètres
volume = lambda l, L, h: l * L * h
print(volume(2, 3, 4))              # 24

# Lambda sans paramètre
bonjour = lambda: "PandaCodeur"
print(bonjour())                    # PandaCodeur
✅ À retenir :
  • Le mot-clé lambda remplace def
  • Pas de parenthèses pour les paramètres (juste après lambda)
  • Pas de return explicite - l'expression est automatiquement retournée
  • Une seule expression (pas d'instructions complexes)

Partie 2 : Lambda vs Fonction classique

2.1 Même fonction, deux écritures

? Exemple 2 : Comparaison directe
# VERSION CLASSIQUE (avec def)
def multiplier_def(a, b):
    return a * b

# VERSION LAMBDA (anonyme)
multiplier_lambda = lambda a, b: a * b

# Les deux s'utilisent de la même façon
print(multiplier_def(3, 4))        # 12
print(multiplier_lambda(3, 4))      # 12

# Vérification : ce sont les mêmes types ?
print(type(multiplier_def))         # 
print(type(multiplier_lambda))       # 
? Exemple 3 : Conditions dans les lambdas
# Lambda avec condition (opérateur ternaire)
est_pair = lambda x: "pair" if x % 2 == 0 else "impair"
print(est_pair(4))      # pair
print(est_pair(7))      # impair

# Équivalent en fonction classique
def est_pair_classique(x):
    if x % 2 == 0:
        return "pair"
    else:
        return "impair"

# Lambda avec conditions multiples
categorie_age = lambda age: "enfant" if age < 12 else "adolescent" if age < 18 else "adulte"
print(categorie_age(8))     # enfant
print(categorie_age(15))    # adolescent
print(categorie_age(25))    # adulte
⚠️ Limitation importante : Les lambdas ne peuvent contenir qu'une seule expression. Pas de boucles for, pas de while, pas d'assignations multiples !
# ❌ Ceci ne fonctionnera PAS :
mauvaise_lambda = lambda x: for i in x: print(i)  # SyntaxError

# ✅ Mais on peut utiliser des expressions complexes :
bonne_lambda = lambda x: [i**2 for i in x]  # OK (compréhension de liste)

Partie 3 : Les lambdas avec les fonctions intégrées

3.1 Lambda avec filter() - On révise !

? Exemple 4 : filter() + lambda
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Filtrer les nombres pairs
pairs = list(filter(lambda x: x % 2 == 0, nombres))
print(pairs)  # [2, 4, 6, 8, 10]

# Filtrer les nombres > 5
grands = list(filter(lambda x: x > 5, nombres))
print(grands)  # [6, 7, 8, 9, 10]

# Application sur des chaînes
mots = ["python", "java", "javascript", "php", "ruby"]
mots_courts = list(filter(lambda mot: len(mot) <= 4, mots))
print(mots_courts)  # ['java', 'php', 'ruby']

3.2 Lambda avec map() - Transformer des données

? map() : Applique une fonction à chaque élément d'une liste et retourne une nouvelle liste avec les résultats.
? Exemple 5 : map() + lambda
nombres = [1, 2, 3, 4, 5]

# Mettre chaque nombre au carré
carres = list(map(lambda x: x ** 2, nombres))
print(carres)  # [1, 4, 9, 16, 25]

# Convertir en degrés Celsius -> Fahrenheit
celsius = [0, 10, 20, 30, 40]
fahrenheit = list(map(lambda c: (c * 9/5) + 32, celsius))
print(fahrenheit)  # [32.0, 50.0, 68.0, 86.0, 104.0]

# Travailler avec des chaînes
noms = ["alice", "bob", "charlie"]
noms_majuscules = list(map(lambda nom: nom.upper(), noms))
print(noms_majuscules)  # ['ALICE', 'BOB', 'CHARLIE']

# Formater des données
prix_ht = [100, 250, 75, 120]
prix_ttc = list(map(lambda p: f"{p * 1.2:.2f} € TTC", prix_ht))
print(prix_ttc)  # ['120.00 € TTC', '300.00 € TTC', '90.00 € TTC', '144.00 € TTC']

3.3 Lambda avec sorted() - Tri personnalisé

? Exemple 6 : sorted() + lambda
# Tri de tuples par le deuxième élément
etudiants = [("Alice", 22), ("Bob", 19), ("Charlie", 25), ("Diana", 21)]
tries_par_age = sorted(etudiants, key=lambda etudiant: etudiant[1])
print("Tri par âge:", tries_par_age)
# [('Bob', 19), ('Diana', 21), ('Alice', 22), ('Charlie', 25)]

# Tri de dictionnaires
personnes = [
    {"nom": "Martin", "age": 45},
    {"nom": "Bernard", "age": 32},
    {"nom": "Petit", "age": 28},
    {"nom": "Durand", "age": 51}
]

tries_par_nom = sorted(personnes, key=lambda p: p["nom"])
print("\nTri par nom:")
for p in tries_par_nom:
    print(f"  {p['nom']} ({p['age']} ans)")

tries_par_age = sorted(personnes, key=lambda p: p["age"], reverse=True)
print("\nTri par âge (décroissant):")
for p in tries_par_age:
    print(f"  {p['nom']} ({p['age']} ans)")

# Tri de chaînes par longueur
mots = ["python", "java", "javascript", "c", "ruby", "typescript"]
tries_par_longueur = sorted(mots, key=lambda mot: len(mot))
print("\nMots triés par longueur:", tries_par_longueur)
# ['c', 'java', 'ruby', 'python', 'javascript', 'typescript']

3.4 Lambda avec max() et min() - Recherche personnalisée

? Exemple 7 : max()/min() + lambda
# Trouver l'étudiant le plus âgé
etudiants = [("Alice", 22), ("Bob", 19), ("Charlie", 25), ("Diana", 21)]
plus_age = max(etudiants, key=lambda e: e[1])
plus_jeune = min(etudiants, key=lambda e: e[1])
print(f"Plus âgé: {plus_age[0]} ({plus_age[1]} ans)")
print(f"Plus jeune: {plus_jeune[0]} ({plus_jeune[1]} ans)")

# Trouver le mot le plus long
mots = ["python", "java", "javascript", "c", "typescript"]
mot_long = max(mots, key=lambda m: len(m))
mot_court = min(mots, key=lambda m: len(m))
print(f"\nMot le plus long: {mot_long} ({len(mot_long)} lettres)")
print(f"Mot le plus court: {mot_court} ({len(mot_court)} lettres)")

# Dans un dictionnaire
ventes = {"janvier": 4500, "février": 5200, "mars": 3800, "avril": 6100}
meilleur_mois = max(ventes.items(), key=lambda m: m[1])
pire_mois = min(ventes.items(), key=lambda m: m[1])
print(f"\nMeilleur mois: {meilleur_mois[0]} ({meilleur_mois[1]}€)")
print(f"Pire mois: {pire_mois[0]} ({pire_mois[1]}€)")

Partie 4 : Cas pratiques avancés

4.1 Lambdas avec plusieurs listes

? Exemple 8 : Combiner des listes
notes = [15, 12, 18, 10, 14]
coefficients = [2, 1, 3, 1, 2]

# Calculer les notes pondérées avec map et zip
notes_ponderees = list(map(lambda x: x[0] * x[1], zip(notes, coefficients)))
print("Notes pondérées:", notes_ponderees)  # [30, 12, 54, 10, 28]

# Moyenne pondérée
moyenne = sum(notes_ponderees) / sum(coefficients)
print(f"Moyenne pondérée: {moyenne:.2f}")  # Moyenne pondérée: 13.33

# Avec 3 listes
noms = ["Alice", "Bob", "Charlie"]
ages = [22, 19, 25]
villes = ["Paris", "Lyon", "Marseille"]

personnes = list(map(lambda a, b, c: f"{a} ({b} ans, {c})", noms, ages, villes))
print("\nPersonnes:", personnes)
# ['Alice (22 ans, Paris)', 'Bob (19 ans, Lyon)', 'Charlie (25 ans, Marseille)']

4.2 Lambdas avec des dictionnaires complexes

? Exemple 9 : Analyser des données
employes = [
    {"nom": "Martin", "prenom": "Jean", "service": "IT", "salaire": 45000, "prime": 5000},
    {"nom": "Bernard", "prenom": "Marie", "service": "Marketing", "salaire": 38000, "prime": 3000},
    {"nom": "Petit", "prenom": "Pierre", "service": "IT", "salaire": 42000, "prime": 4500},
    {"nom": "Durand", "prenom": "Sophie", "service": "RH", "salaire": 35000, "prime": 2000},
    {"nom": "Leroy", "prenom": "Paul", "service": "IT", "salaire": 48000, "prime": 6000}
]

# 1. Calculer le salaire total (salaire + prime) pour chaque employé
employes_avec_total = list(map(
    lambda e: {**e, "total": e["salaire"] + e["prime"]}, 
    employes
))

print("Employés avec salaire total:")
for e in employes_avec_total[:3]:  # Afficher les 3 premiers
    print(f"  {e['prenom']} {e['nom']}: {e['total']}€")

# 2. Filtrer les employés IT avec total > 45000
it_bien_payes = list(filter(
    lambda e: e["service"] == "IT" and (e["salaire"] + e["prime"]) > 45000,
    employes
))

print("\nIT bien payés (>45000€):")
for e in it_bien_payes:
    print(f"  {e['prenom']} {e['nom']}: {e['salaire'] + e['prime']}€")

# 3. Trier par salaire total décroissant
tries_par_total = sorted(employes, key=lambda e: e["salaire"] + e["prime"], reverse=True)

print("\nClassement par salaire total:")
for i, e in enumerate(tries_par_total, 1):
    total = e["salaire"] + e["prime"]
    print(f"  {i}. {e['prenom']} {e['nom']}: {total}€")

4.3 Lambdas dans des expressions conditionnelles

? Exemple 10 : Lambdas dynamiques
# Créer des fonctions de calcul selon un choix
def creer_operation(operateur):
    if operateur == "+":
        return lambda a, b: a + b
    elif operateur == "-":
        return lambda a, b: a - b
    elif operateur == "*":
        return lambda a, b: a * b
    elif operateur == "/":
        return lambda a, b: a / b if b != 0 else "Division par zéro"
    else:
        return lambda a, b: "Opérateur inconnu"

# Utilisation
addition = creer_operation("+")
print(addition(10, 5))  # 15

multiplication = creer_operation("*")
print(multiplication(10, 5))  # 50

# Lambda qui choisit une lambda selon une condition
calcul_adapte = lambda x: (lambda y: y * 2) if x > 0 else (lambda y: y / 2)
fonction = calcul_adapte(10)
print(fonction(20))  # 40 (car 10 > 0, donc multiplication par 2)

fonction = calcul_adapte(-5)
print(fonction(20))  # 10.0 (car -5 < 0, donc division par 2)

Partie 5 : Exercices pratiques avec corrigés

Exercice 1 : Gestion de notes

etudiants = [
    {"nom": "Alice", "notes": [15, 18, 12, 14]},
    {"nom": "Bob", "notes": [8, 12, 10, 9]},
    {"nom": "Charlie", "notes": [19, 17, 18, 20]},
    {"nom": "Diana", "notes": [14, 13, 15, 12]}
]
  1. Calcule la moyenne de chaque étudiant en utilisant map() et lambda
  2. Filtre les étudiants qui ont la moyenne (≥ 10)
  3. Trie les étudiants par moyenne décroissante
  4. Trouve le meilleur étudiant

Exercice 2 : Panier d'achat

panier = [
    {"produit": "pommes", "prix": 2.5, "quantite": 6, "tva": 5.5},
    {"produit": "bananes", "prix": 1.8, "quantite": 4, "tva": 5.5},
    {"produit": "chocolat", "prix": 3.5, "quantite": 2, "tva": 20},
    {"produit": "café", "prix": 8.5, "quantite": 1, "tva": 20},
    {"produit": "yaourts", "prix": 1.2, "quantite": 12, "tva": 5.5}
]
  1. Ajoute un champ "prix_ttc" à chaque produit (prix * (1 + tva/100))
  2. Calcule le total TTC du panier
  3. Filtre les produits dont le prix TTC unitaire est > 3€
  4. Trie les produits par prix TTC décroissant

Exercice 3 : Analyse de texte

phrases = [
    "Python est un langage génial",
    "Les fonctions lambda sont pratiques",
    "Apprendre à programmer est amusant",
    "Les listes et dictionnaires sont utiles"
]
  1. Compte le nombre de mots dans chaque phrase
  2. Trouve la phrase la plus longue (en nombre de mots)
  3. Convertit toutes les phrases en majuscules
  4. Filtre les phrases qui contiennent le mot "lambda"

Solutions 

Solution Exercice 1

etudiants = [
    {"nom": "Alice", "notes": [15, 18, 12, 14]},
    {"nom": "Bob", "notes": [8, 12, 10, 9]},
    {"nom": "Charlie", "notes": [19, 17, 18, 20]},
    {"nom": "Diana", "notes": [14, 13, 15, 12]}
]

# 1. Calculer les moyennes
etudiants_avec_moyenne = list(map(
    lambda e: {**e, "moyenne": sum(e["notes"]) / len(e["notes"])},
    etudiants
))

print("1. Étudiants avec leur moyenne:")
for e in etudiants_avec_moyenne:
    print(f"  {e['nom']}: {e['moyenne']:.2f}")

# 2. Filtrer ceux qui ont la moyenne (≥ 10)
admis = list(filter(lambda e: e["moyenne"] >= 10, etudiants_avec_moyenne))
print("\n2. Étudiants admis:")
for e in admis:
    print(f"  {e['nom']}: {e['moyenne']:.2f}")

# 3. Trier par moyenne décroissante
classement = sorted(etudiants_avec_moyenne, key=lambda e: e["moyenne"], reverse=True)
print("\n3. Classement:")
for i, e in enumerate(classement, 1):
    print(f"  {i}. {e['nom']}: {e['moyenne']:.2f}")

# 4. Meilleur étudiant
meilleur = max(etudiants_avec_moyenne, key=lambda e: e["moyenne"])
print(f"\n4. Meilleur étudiant: {meilleur['nom']} avec {meilleur['moyenne']:.2f} de moyenne")

Solution Exercice 2

panier = [
    {"produit": "pommes", "prix": 2.5, "quantite": 6, "tva": 5.5},
    {"produit": "bananes", "prix": 1.8, "quantite": 4, "tva": 5.5},
    {"produit": "chocolat", "prix": 3.5, "quantite": 2, "tva": 20},
    {"produit": "café", "prix": 8.5, "quantite": 1, "tva": 20},
    {"produit": "yaourts", "prix": 1.2, "quantite": 12, "tva": 5.5}
]

# 1. Ajouter prix TTC
panier_ttc = list(map(
    lambda p: {
        **p, 
        "prix_ttc": round(p["prix"] * (1 + p["tva"]/100), 2),
        "total_ttc": round(p["prix"] * (1 + p["tva"]/100) * p["quantite"], 2)
    },
    panier
))

print("1. Panier avec prix TTC:")
for p in panier_ttc:
    print(f"  {p['produit']}: {p['prix_ttc']}€ (x{p['quantite']} = {p['total_ttc']}€)")

# 2. Total du panier
total_panier = sum(map(lambda p: p["total_ttc"], panier_ttc))
print(f"\n2. Total du panier: {total_panier:.2f}€")

# 3. Produits avec prix TTC unitaire > 3€
produits_chers = list(filter(lambda p: p["prix_ttc"] > 3, panier_ttc))
print("\n3. Produits > 3€:")
for p in produits_chers:
    print(f"  {p['produit']}: {p['prix_ttc']}€")

# 4. Tri par prix TTC décroissant
panier_trie = sorted(panier_ttc, key=lambda p: p["prix_ttc"], reverse=True)
print("\n4. Produits triés par prix décroissant:")
for p in panier_trie:
    print(f"  {p['produit']}: {p['prix_ttc']}€")

Solution Exercice 3

phrases = [
    "Python est un langage génial",
    "Les fonctions lambda sont pratiques",
    "Apprendre à programmer est amusant",
    "Les listes et dictionnaires sont utiles"
]

# 1. Compter les mots
nombres_mots = list(map(lambda p: len(p.split()), phrases))
print("1. Nombre de mots par phrase:")
for i, (phrase, nb) in enumerate(zip(phrases, nombres_mots)):
    print(f"  Phrase {i+1}: {nb} mots")

# 2. Phrase la plus longue
phrase_longue = max(phrases, key=lambda p: len(p.split()))
nb_mots = len(phrase_longue.split())
print(f"\n2. Phrase la plus longue ({nb_mots} mots):")
print(f"  \"{phrase_longue}\"")

# 3. Convertir en majuscules
phrases_maj = list(map(lambda p: p.upper(), phrases))
print("\n3. Phrases en majuscules:")
for p in phrases_maj:
    print(f"  {p}")

# 4. Filtrer celles avec "lambda"
phrases_lambda = list(filter(lambda p: "lambda" in p.lower(), phrases))
print("\n4. Phrases contenant 'lambda':")
if phrases_lambda:
    for p in phrases_lambda:
        print(f"  \"{p}\"")
else:
    print("  Aucune phrase ne contient le mot 'lambda'")

Bonus : Techniques avancées avec les lambdas

? Exemple Bonus : Fonctions d'ordre supérieur
# Une fonction qui retourne une lambda
def multiplicateur(facteur):
    return lambda x: x * facteur

double = multiplicateur(2)
triple = multiplicateur(3)

print(double(10))  # 20
print(triple(10))  # 30

# Composition de fonctions
def compose(f, g):
    return lambda x: f(g(x))

carre = lambda x: x ** 2
incremente = lambda x: x + 1

carre_et_incremente = compose(incremente, carre)
incremente_et_carre = compose(carre, incremente)

print(carre_et_incremente(5))  # (5²) + 1 = 26
print(incremente_et_carre(5))  # (5+1)² = 36

# Évaluation paresseuse (lazy evaluation)
def creer_comparateur(seuil):
    return lambda x: x > seuil

est_superieur_a_10 = creer_comparateur(10)
est_superieur_a_100 = creer_comparateur(100)

nombres = [5, 15, 25, 105]
print(list(filter(est_superieur_a_10, nombres)))   # [15, 25, 105]
print(list(filter(est_superieur_a_100, nombres)))  # [105]
? Résumé des points clés à retenir sur les lambdas :
  • Syntaxe : lambda paramètres: expression
  • Pas de return : l'expression est automatiquement retournée
  • Une seule ligne : idéal pour des fonctions simples et jetables
  • Parfait avec : filter(), map(), sorted(), max(), min()
  • À éviter pour : des fonctions complexes avec plusieurs instructions
  • Peut être assignée : à une variable pour la réutiliser (mais on perd l'intérêt de l'anonymat)
⚠️ Quand NE PAS utiliser de lambda :
  • Fonctions de plus d'une ligne
  • Fonctions avec des boucles
  • Fonctions complexes avec plusieurs conditions imbriquées
  • Quand la lisibilité du code est plus importante que la concision
  • Pour des fonctions réutilisées à plusieurs endroits (préférer def)
? Statistiques d'utilisation :
Fonction Utilisation typique avec lambda Fréquence
sorted() Tri personnalisé avec key= ⭐⭐⭐⭐⭐
filter() Filtrage conditionnel ⭐⭐⭐⭐
map() Transformation de données ⭐⭐⭐⭐
max()/min() Trouver l'élément selon un critère ⭐⭐⭐

 

✨ Les lambdas sont comme des couteaux suisses : pratiques pour les petites tâches rapides, mais mieux vaut utiliser des outils plus adaptés pour les gros travaux !

 

Questions / Réponses

Aucune question. Soyez le premier à poser une question.
Aucune note. Soyez le premier à attribuer une note !

Ajouter un commentaire

Anti-spam