9. Les fonctions avancées en Python
Approfondissez vos connaissances sur les fonctions Python : paramètres par défaut, fonctions lambda, décorateurs et récursion.
PYTHON pour les DÉBUTANTS #9#
Les fonctions avancées en Python#
Maintenant que vous maîtrisez les bases des fonctions, découvrons les concepts avancés qui vous permettront d’écrire du code plus élégant et réutilisable.
Paramètres par défaut#
Explication
Les paramètres par défaut permettent de rendre certains arguments optionnels en leur donnant une valeur par défaut qui sera utilisée si l’appelant ne fournit pas de valeur.
Syntaxe de base#
def saluer(nom, message="Bonjour"): return f"{message}, {nom}!"
# Utilisation avec paramètre par défautprint(saluer("Alice")) # "Bonjour, Alice!"
# Utilisation avec paramètre personnaliséprint(saluer("Bob", "Salut")) # "Salut, Bob!"Paramètres par défaut multiples#
def creer_profil(nom, age=25, ville="Paris", actif=True): return { "nom": nom, "age": age, "ville": ville, "actif": actif }
# Utilisation avec différents paramètresprofil1 = creer_profil("Alice")profil2 = creer_profil("Bob", 30)profil3 = creer_profil("Charlie", ville="Lyon")Attention
Les paramètres avec valeurs par défaut doivent toujours être placés après les paramètres obligatoires dans la signature de la fonction.
Arguments nommés et positionnels#
Python permet de passer les arguments par position ou par nom.
Arguments positionnels#
def calculer_prix(prix_base, tva=0.2, remise=0): prix_final = prix_base * (1 + tva) * (1 - remise) return prix_final
# Arguments par positionprix1 = calculer_prix(100, 0.1, 0.05)Arguments nommés#
# Arguments par nom (plus lisible)prix2 = calculer_prix( prix_base=100, remise=0.1, tva=0.2)Conseil
Les arguments nommés rendent votre code plus lisible et permettent de passer les arguments dans n’importe quel ordre. Ils sont particulièrement utiles pour les fonctions avec de nombreux paramètres.
Fonctions avec un nombre variable d’arguments#
*args (arguments positionnels variables)#
def additionner(*nombres): total = 0 for nombre in nombres: total += nombre return total
# Utilisationresultat1 = additionner(1, 2, 3) # 6resultat2 = additionner(1, 2, 3, 4, 5) # 15Définition
*args permet de passer un nombre variable d’arguments positionnels à une fonction. Les arguments sont rassemblés dans un tuple accessible via le nom args.
**kwargs (arguments nommés variables)#
def creer_configuration(**options): config = { "debug": False, "timeout": 30, "retry": 3 } config.update(options) return config
# Utilisationconfig1 = creer_configuration(debug=True)config2 = creer_configuration(timeout=60, retry=5)Combinaison *args et **kwargs#
def fonction_complete(*args, **kwargs): print("Arguments positionnels:", args) print("Arguments nommés:", kwargs)
fonction_complete(1, 2, 3, nom="Alice", age=25)Fonctions lambda (fonctions anonymes)#
Définition
Les fonctions lambda permettent de créer des fonctions simples en une ligne. Elles sont particulièrement utiles pour des opérations courtes utilisées comme arguments d’autres fonctions.
Syntaxe de base#
# Fonction normaledef carre(x): return x ** 2
# Fonction lambda équivalentecarre_lambda = lambda x: x ** 2
print(carre(5)) # 25print(carre_lambda(5)) # 25Utilisation avec les fonctions intégrées#
```python title=“Lambda avec map(), filter() et sorted()” showLineNumbers
nombres = [1, 2, 3, 4, 5]
Utilisation avec map()#
carres = list(map(lambda x: x ** 2, nombres)) print(carres) # [1, 4, 9, 16, 25]
Utilisation avec filter()#
pairs = list(filter(lambda x: x % 2 == 0, nombres)) print(pairs) # [2, 4]
Utilisation avec sorted()#
noms = [“Alice”, “Bob”, “Charlie”] noms_tries = sorted(noms, key=lambda nom: len(nom)) print(noms_tries) # [“Bob”, “Alice”, “Charlie”]
<Callout variant="tip">Les fonctions lambda sont idéales pour des opérations simples. Pour des logiques plus complexes, préférez les fonctions normales avec `python:def` qui sont plus lisibles et peuvent contenir plusieurs instructions.</Callout>
## Fonctions comme objets de première classe
En Python, les fonctions sont des objets comme les autres.
### Assignation de fonctions
```python title="Assignation et manipulation de fonctions" showLineNumbersdef dire_bonjour(): return "Bonjour!"
def dire_aurevoir(): return "Au revoir!"
# Assignation de fonctionsalutation = dire_bonjourprint(salutation()) # "Bonjour!"
salutation = dire_aurevoirprint(salutation()) # "Au revoir!"Fonctions comme paramètres#
def appliquer_operation(nombres, operation): resultats = [] for nombre in nombres: resultats.append(operation(nombre)) return resultats
def doubler(x): return x * 2
def tripler(x): return x * 3
nombres = [1, 2, 3, 4, 5]
# Utilisationdoubles = appliquer_operation(nombres, doubler)triples = appliquer_operation(nombres, tripler)
print(doubles) # [2, 4, 6, 8, 10]print(triples) # [3, 6, 9, 12, 15]Fonctions imbriquées et closures#
Fonctions imbriquées#
def calculatrice(): def addition(a, b): return a + b
def soustraction(a, b): return a - b
def multiplication(a, b): return a * b
return { "add": addition, "sub": soustraction, "mul": multiplication }
# Utilisationcalc = calculatrice()resultat = calc["add"](5, 3) # 8Closures (fermetures)#
Explication
Une closure est une fonction qui “capture” des variables de sa portée environnante. Elle peut accéder et modifier ces variables même après que la fonction externe ait terminé son exécution.
def creer_multiplicateur(facteur): def multiplier(nombre): return nombre * facteur return multiplier
# Création de fonctions spécialiséesmultiplier_par_2 = creer_multiplicateur(2)multiplier_par_3 = creer_multiplicateur(3)
print(multiplier_par_2(5)) # 10print(multiplier_par_3(5)) # 15Décorateurs (introduction)#
Définition
Les décorateurs permettent de modifier le comportement des fonctions sans changer leur code source. Ils “enveloppent” une fonction pour ajouter des fonctionnalités supplémentaires.
Décorateur simple#
def chronometrer(fonction): def wrapper(*args, **kwargs): import time debut = time.time() resultat = fonction(*args, **kwargs) fin = time.time() print(f"Temps d'exécution: {fin - debut:.2f} secondes") return resultat return wrapper
@chronometrerdef calcul_long(): total = 0 for i in range(1000000): total += i return total
resultat = calcul_long()Récursion#
Explication
La récursion permet à une fonction de s’appeler elle-même. C’est une technique puissante pour résoudre des problèmes qui peuvent être décomposés en sous-problèmes similaires.
Exemple classique : factorielle#
def factorielle(n): if n <= 1: return 1 else: return n * factorielle(n - 1)
print(factorielle(5)) # 120Exemple : suite de Fibonacci#
def fibonacci(n): if n <= 1: return n else: return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # 55Attention
La récursion peut être inefficace pour certains problèmes comme Fibonacci, car elle recalcule les mêmes valeurs plusieurs fois. Utilisez la mémorisation ou l’itération pour améliorer les performances.
Récursion avec mémorisation#
def fibonacci_memo(n, memo={}): if n in memo: return memo[n] if n <= 1: return n memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo) return memo[n]
print(fibonacci_memo(50)) # Beaucoup plus rapide !Bonnes pratiques#
Documentation des fonctions#
def calculer_moyenne(nombres): """ Calcule la moyenne d'une liste de nombres.
Args: nombres (list): Liste de nombres à moyenner
Returns: float: La moyenne des nombres
Raises: ValueError: Si la liste est vide """ if not nombres: raise ValueError("La liste ne peut pas être vide")
return sum(nombres) / len(nombres)Conseil
Utilisez des docstrings pour documenter vos fonctions. Elles aident les autres développeurs (et vous-même plus tard) à comprendre ce que fait votre fonction, quels paramètres elle accepte, et ce qu’elle retourne.
Gestion des erreurs#
def diviser(a, b): try: return a / b except ZeroDivisionError: print("Erreur: Division par zéro") return None except TypeError: print("Erreur: Types invalides") return NoneExercices pratiques#
Conseil
-
Calculatrice avancée : Créez une calculatrice avec des opérations personnalisées.
-
Filtre de données : Utilisez des fonctions lambda pour filtrer des listes de données.
-
Décorateur de logging : Créez un décorateur qui enregistre les appels de fonction.
-
Fonction récursive : Implémentez une fonction pour parcourir un arbre de répertoires.
Conclusion#
Les fonctions avancées en Python offrent une grande flexibilité :
- Paramètres par défaut : Pour des fonctions plus pratiques
- Arguments variables (
*args,**kwargs) : Pour une adaptabilité maximale - Fonctions
lambda: Pour des opérations simples et élégantes - Closures : Pour créer des fonctions spécialisées
- Récursion : Pour résoudre des problèmes complexes
Maîtrisez ces concepts et vous écrirez du code Python plus professionnel et maintenable !