Séance 05 · Partie A · Python pas à pas
Fonctions.
Un grand programme est fait de petits morceaux qui font chacun une chose, bien. Une fonction, c’est un de ces morceaux, avec un nom.
Durée : 60 à 90 min · Objectifs : définir et appeler une fonction, paramètres et valeurs de retour, portée des variables, documenter et tester.
Ce que vous saurez faire à la fin
- Transformer un bloc de code répété en fonction réutilisable.
- Distinguer
print(afficher) etreturn(renvoyer). - Comprendre pourquoi une variable créée dans une fonction n’existe pas dehors.
- Découper un problème en fonctions avant de coder.
01 / Définir
def : donner un nom à un bloc
def+ nom +()+:définit la fonction. Rien ne s’exécute encore.saluer()appelle la fonction : le bloc s’exécute.- Définir une fois, appeler autant de fois qu’on veut.
Les parenthèses sont obligatoires à l’appel. saluer sans parenthèses désigne la fonction sans la lancer.
Vous en utilisez depuis le début
print(), input(), len(), int(), range() sont des fonctions écrites par les créateurs de Python. Aujourd’hui vous écrivez les vôtres. Le mécanisme est identique.
01 / Définir
Les paramètres : donner des informations à la fonction
distanceetvitessesont les paramètres : des variables qui reçoivent les valeurs à chaque appel.100et20sont les arguments passés à cet appel.- On peut nommer les arguments pour plus de clarté.
Valeur par défaut
def avancer(distance, vitesse=20): rend vitesse optionnel : avancer(100) utilise 20. Les paramètres avec défaut se placent après ceux sans défaut. C’est ainsi que print(x, end=" ") fonctionne : end a la valeur par défaut "\n".
02 / Renvoyer
return : la fonction donne un résultat
returnrenvoie une valeur à l’endroit de l’appel et termine la fonction.- L’appel
aire_disque(2)devient la valeur 12.57 : on peut la ranger, l’afficher, la calculer. - Une fonction sans
returnrenvoieNone.
02 / Renvoyer
print n’est pas return
L’erreur la plus fréquente de la séance
print montre une valeur à l’humain. return donne une valeur au programme. Une fonction de calcul doit renvoyer ; l’affichage se décide ailleurs. Décommentez la dernière ligne : double_affiche(3) renvoie None, et None * 2 est une TypeError. Règle pratique : si vous écrivez print dans une fonction de calcul, demandez-vous si ce n’est pas return que vous vouliez.
02 / Renvoyer
Renvoyer plusieurs valeurs, ou un booléen
Style
On écrit return n % 2 == 0 et non if n % 2 == 0: return True else: return False : la comparaison est déjà un booléen. Les fonctions qui renvoient un booléen se nomment souvent est_… ou a_… : le if se lit alors comme une phrase.
03 / Portée
Ce qui naît dans une fonction meurt avec elle
resultatest locale : elle existe seulement pendant l’exécution decalcul().- À l’extérieur, ce nom n’existe pas. C’est voulu : chaque fonction a son espace privé.
- Pour récupérer la valeur :
return, puis une variable extérieure.
Lecture de l’extérieur, écriture interdite
Une fonction peut lire une variable définie hors d’elle (dite globale), par exemple une constante GRAVITE = 9.81. Mais elle ne peut pas la modifier par simple affectation : elle créerait une locale du même nom. Le mot-clé global l’autorise, mais son usage est presque toujours signe d’un mauvais découpage. Préférez passer des paramètres et renvoyer des résultats : la fonction devient prévisible et testable.
03 / Portée
Même nom, variables différentes
Pourquoi c’est une bonne chose
Imaginez un programme de 5000 lignes écrit par cinq personnes. Si chaque fonction pouvait modifier n’importe quelle variable, personne ne pourrait raisonner sur rien. L’isolation des fonctions est ce qui permet de construire des logiciels de la taille d’un système d’exploitation ou d’un robot autonome. En séance 06, une nuance importante : une fonction qui reçoit une liste peut en modifier le contenu.
04 / Bien écrire
Documenter et tester une fonction
Pourquoi tester ?
La docstring (chaîne entre triples guillemets juste sous def) explique ce que fait la fonction ; help() l’affiche. Les assert vérifient des cas connus. Changez le 9 en 8 dans la formule : le premier test échoue immédiatement, avant que l’erreur ne se propage dans un programme de 1000 lignes. Les ingénieurs écrivent souvent les tests avant la fonction : ils savent alors précisément ce qu’ils doivent produire.
04 / Bien écrire
Découper un problème
Une fonction, une responsabilité
Chaque fonction fait une chose et son nom le dit. decider() ne lit pas de capteur et n’affiche rien : on peut la tester seule (assert decider(5) == "reculer"). Quand vous passerez au vrai robot, seules lire_capteur() et agir() changeront ; decider() restera identique. Cette séparation entre perception, décision et action est un principe de base en robotique. Le _ comme variable de boucle signale « je n’utilise pas cette valeur ».
05 / Défis
Défi ★ — Trois petites fonctions
Consigne
Écrire et tester : perimetre_rectangle(l, L), maximum3(a, b, c) (sans utiliser max) et est_majuscule(lettre) qui renvoie un booléen.
Correction
def perimetre_rectangle(l, L):
return 2 * (l + L)
def maximum3(a, b, c):
m = a
if b > m:
m = b
if c > m:
m = c
return m
def est_majuscule(lettre):
return "A" <= lettre <= "Z"
assert perimetre_rectangle(2, 3) == 10
assert maximum3(3, 9, 5) == 9 and maximum3(3, 3, 3) == 3
assert est_majuscule("R") and not est_majuscule("r")
print("OK")Les lettres se comparent par ordre alphabétique (en réalité par code Unicode, séance 07). pass est une instruction qui ne fait rien : utile pour laisser un bloc vide provisoirement.
05 / Défis
Défi ★★ — Nombres premiers
Consigne
Écrire est_premier(n) qui renvoie True si n est premier (divisible seulement par 1 et lui-même, n ≥ 2). Puis afficher tous les nombres premiers inférieurs à 100 grâce à cette fonction.
Correction
def est_premier(n):
if n < 2:
return False
for d in range(2, n):
if n % d == 0:
return False # un diviseur trouvé : on sort tout de suite
return True # aucun diviseur : premier
for n in range(2, 100):
if est_premier(n):
print(n, end=" ")Le return False dans la boucle joue le rôle d’un break : dès qu’on sait, on répond. Amélioration : il suffit de tester les diviseurs jusqu’à √n (si n = a × b, l’un des deux est ≤ √n). Écrivez range(2, int(n ** 0.5) + 1) et comparez le temps pour n = 10 000 019 avec time.perf_counter(). Ce sera l’objet de la séance 11.
05 / Défis
Défi ★★★ — Esprit prépa : la racine carrée de Héron
Consigne
Il y a 2000 ans, Héron d’Alexandrie calculait √a ainsi : partir de x = a, puis répéter x = (x + a / x) / 2. Chaque étape double environ le nombre de décimales exactes.
Écrire racine(a, precision=1e-10) qui répète tant que |x² − a| > precision et renvoie x. Comparer avec a ** 0.5. Compter le nombre d’itérations pour a = 2, 1000, 1 000 000.
Correction et ouverture
def racine(a, precision=1e-10):
x = a
iterations = 0
while abs(x * x - a) > precision:
x = (x + a / x) / 2
iterations += 1
return x, iterations
for a in (2, 1000, 1_000_000):
r, n = racine(a)
print(f"√{a} ≈ {r:.10f} en {n} itérations (Python : {a ** 0.5:.10f})")Même pour un million, une quinzaine d’itérations suffisent : la convergence est quadratique. Cette méthode est un cas particulier de la méthode de Newton, que vous verrez en prépa, et c’est (à peu près) ce que fait le processeur de votre PC quand il calcule une racine. Question ouverte : pourquoi partir de x = a et pas de x = 1 ? Essayez les deux. Et que se passe-t-il pour a = 0 ?
06 / Vérification
Qu’affiche print(f(3)) si def f(x): return x + 5 ?
Deux questions supplémentaires
1. Que renvoie une fonction qui n’a pas de return ? None.
2. Peut-on avoir deux return dans une fonction ? Oui, par exemple dans les deux branches d’un if. Le premier atteint termine la fonction.
Référence
Les mots à retenir
| Mot | Définition |
|---|---|
| Fonction | Bloc de code nommé, réutilisable, avec entrées et sortie. |
| Paramètre | Variable de la fonction qui reçoit une valeur à l’appel. |
| Argument | Valeur effectivement passée lors d’un appel. |
return | Renvoie un résultat et termine la fonction. |
| Variable locale | Créée dans la fonction, invisible dehors. |
| Docstring | Texte de documentation sous le def. |
assert | Vérifie qu’une condition est vraie, sinon erreur. |
Pour continuer
Vous savez construire des briques
Séance suivante : les listes et dictionnaires, pour donner à vos fonctions de vraies données à traiter.
À faire chez soi
- Reprendre les défis des séances 02 à 04 et les réécrire sous forme de fonctions testées avec
assert. - Écrire
pgcd(a, b)avec l’algorithme d’Euclide : tant que b ≠ 0, (a, b) devient (b, a % b). - Écrire
chiffre_de_cesar(texte, decalage)qui décale chaque lettre. Indice :ord()etchr().