Fonctions
Progression
#Fonctions
À quoi ça sert: isoler une logique réutilisable et testable, réduire la duplication et documenter le contrat d’entrée/sortie. Comment: paramètres (positionnels/nommés), valeurs par défaut, retour, docstrings et annotations.
Objectifs d’apprentissage
- Déclarer des fonctions claires (noms, docstrings, annotations de type).
- Maîtriser les paramètres: positionnels, nommés, par défaut, variadiques (
*args
,**kwargs
).- Comprendre la liaison des noms lors du passage d’arguments et éviter les valeurs par défaut mutables.
1def area(w: float, h: float) -> float:2 """Retourne l'aire d'un rectangle."""3 return w * h4 5print(area(3, 4))
Arguments nommés et valeurs par défaut:
1def power(x, exp=2):2 return x ** exp3 4print(power(3), power(2, exp=3))
Paramètres positionnels/nommés, mots‑clés‑seulement et variadiques:
1def normalize(values: list[float], *, eps: float = 1e-9) -> list[float]:2 m, M = min(values), max(values)3 span = max(eps, M - m)4 return [(v - m) / span for v in values]5 6def summarize(title: str, *points: str, **meta):7 print(f"# {title}")8 for p in points:9 print("-", p)10 if meta:11 print("(meta)", meta)12 13summarize("Plan", "a", "b", owner="alice")
Variables locales vs globales: préférer le passage de paramètres aux effets globaux.
#Récursion
1def fact(n: int) -> int:2 return 1 if n <= 1 else n * fact(n-1)3 4print(fact(5))
#Visualiser la pile d'appels
#Playground
#Exercices
- Écrire
pgcd(a,b)
(algorithme d’Euclide). - Écrire
fib(n)
avec mémoïsation (dict). - Écrire une fonction qui normalise une liste de nombres entre 0 et 1.
- Implémenter un décorateur pour mesurer le temps d'exécution d'une fonction.
Astuce pour démarrer: écrivez d’abord des tests d’exemples attendus (entrées → sorties). Une bonne fonction prend ses données en paramètres, ne lit pas d’état global, et retourne le résultat plutôt que d’imprimer directement.
#Solutions (exemples)
- Implémenter un décorateur pour mesurer le temps d'exécution d'une fonction.
#Pièges fréquents
Valeurs par défaut mutables:
1def append_bad(item, bucket=[]): # Anti‑pattern2 bucket.append(item)3 return bucket4 5print(append_bad(1))6print(append_bad(2)) # Surprise: partage le même bucket !7 8def append_ok(item, bucket=None):9 if bucket is None:10 bucket = []11 bucket.append(item)12 return bucket
Annotations de type et docstrings:
1def area(w: float, h: float) -> float:2 """Retourne l'aire d'un rectangle.3 4 Args:5 w: largeur (>= 0)6 h: hauteur (>= 0)7 Returns:8 Aire (w*h).9 """10 return w * h
Faire b = a
ne copie pas une liste, cela crée un deuxième nom pour le même objet. Utilisez a.copy()
ou list(a)
si vous avez besoin d’une copie superficielle.
Une docstring courte avec un exemple d’usage (doctest) sert de documentation et de test rapide.