SunuLab
Notre savoir
CoursIntermédiaire13 min de lecture

Les fonctions

Découper un programme en outils réutilisables : def, paramètres, return, et la portée des variables

§1.Tu en utilises depuis le premier chapitre

print(), input(), len(), range(), sorted() — ce sont toutes des FONCTIONS. Quelqu'un a écrit le code compliqué une fois, l'a rangé sous un nom simple, et depuis, le monde entier l'utilise sans savoir comment il marche.

Écrire tes propres fonctions, c'est passer du côté de celui qui fabrique les outils. C'est probablement la compétence qui sépare le plus nettement le débutant du programmeur.

L'intérêt n'est pas seulement d'éviter de se répéter. C'est de pouvoir raisonner sur un morceau de programme ISOLÉMENT : une fonction bien écrite se comprend, se teste et se corrige sans avoir le reste en tête.

Une première fonction
python
def saluer():
print("Bonjour !")
print("Comment vas-tu ?")
# Ici, rien ne s'est encore affiché.
saluer()
saluer()
Résultat : Bonjour ! Comment vas-tu ? Bonjour ! Comment vas-tu ?

DÉFINIR une fonction avec def, c'est écrire le mode d'emploi : rien ne s'exécute. C'est l'APPEL — le nom suivi de parenthèses — qui déclenche le travail. Et il faut définir avant d'appeler.

§3.Anatomie

def nom(parametres):
Le mot-clé def, un nom de ton choix, les paramètres entre parenthèses, puis deux-points. Le corps est indenté en dessous, comme pour un if.
Paramètre et argument
Le PARAMÈTRE est le nom écrit dans la définition ; l'ARGUMENT est la valeur réellement passée à l'appel. On confond souvent les deux, sans grande conséquence.
Exemple. def carre(n) — n est un paramètre. carre(5) — 5 est un argument.
return
Renvoie une valeur à celui qui a appelé, et termine immédiatement la fonction. Sans return, la fonction renvoie None.

§4.La distinction qui compte : afficher ou renvoyer

C'est LE point de bascule du chapitre, et la source d'erreur numéro un dans les exercices.

print() envoie du texte à l'écran, pour un humain. Le programme, lui, n'en récupère rien. return donne une VALEUR au programme, qui peut la stocker, la calculer, la comparer — mais rien ne s'affiche.

Une fonction qui affiche au lieu de renvoyer est un cul-de-sac : on ne peut rien faire de son travail.

La différence, en action
python
def carre_affiche(n):
print(n * n)
def carre_renvoie(n):
return n * n
carre_affiche(5)
resultat = carre_renvoie(5)
print(resultat + 1)
perdu = carre_affiche(5)
print(perdu)
Résultat : 25 26 25 None

carre_renvoie permet de continuer à calculer. carre_affiche, non : sa valeur de retour est None, parce qu'elle n'a pas de return. Retiens la règle : une fonction CALCULE et renvoie ; c'est l'appelant qui décide d'afficher.

Vérifie-le toi-même
Chargement de l'éditeur Python…
Plusieurs paramètres, valeurs par défaut
python
def moyenne(notes, arrondi=2):
if len(notes) == 0:
return 0
return round(sum(notes) / len(notes), arrondi)
print(moyenne([12, 15, 9]))
print(moyenne([12, 15, 9], 0))
print(moyenne([12, 15, 9], arrondi=4))
Résultat : 12.0 12.0 12.0

Un paramètre avec une valeur PAR DÉFAUT devient facultatif. On peut aussi nommer les arguments à l'appel (arrondi=4), ce qui rend le code bien plus lisible quand une fonction en prend plusieurs.

Sortir tôt, ou accumuler
python
def contient_negatif(liste):
for x in liste:
if x < 0:
return True # on sait déjà : inutile de continuer
return False # on n'a rien trouvé
def somme_positifs(liste):
total = 0
for x in liste:
if x > 0:
total = total + x
return total # APRÈS la boucle, pas dedans
print(contient_negatif([1, -2, 3]))
print(contient_negatif([1, 2, 3]))
print(somme_positifs([1, -2, 3]))
Résultat : True False 4

§10.La portée des variables

Une variable créée DANS une fonction n'existe que pendant son exécution. À l'extérieur, elle est inconnue : c'est une variable LOCALE.

Cette étanchéité est une protection, pas une contrainte. Elle garantit qu'une fonction ne peut pas casser accidentellement le reste du programme — et c'est justement ce qui permet de raisonner sur elle isolément.

Une fonction peut LIRE une variable définie à l'extérieur, mais si elle lui affecte une valeur, Python en crée une nouvelle, locale, sans toucher à l'originale.

Locale contre globale
python
compteur = 0
def incremente():
compteur = 100 # crée une variable LOCALE
return compteur
print(incremente())
print(compteur) # l'originale n'a pas bougé
Résultat : 100 0

Plutôt que de chercher à modifier des variables extérieures — ce qui rend un programme imprévisible — passe les valeurs en PARAMÈTRES et récupère le résultat avec return. C'est la bonne façon de faire circuler l'information.

Composer des fonctions
python
def est_pair(n):
return n % 2 == 0
def pairs_de(liste):
return [x for x in liste if est_pair(x)]
def resume(liste):
p = pairs_de(liste)
return len(p), sum(p)
nombre, total = resume([1, 2, 3, 4, 5, 6])
print(nombre, total)
Résultat : 3 12

Une fonction peut en appeler d'autres — c'est même le but. Remarque aussi qu'on peut renvoyer PLUSIEURS valeurs d'un coup, séparées par des virgules, et les récupérer en une ligne.

§13.Ce qui fait une bonne fonction

Un nom qui dit ce qu'elle fait
calculer_moyenne() est bon, truc() est inutile. Un verbe à l'infinitif pour une action, une question pour un booléen : est_premier(), contient_negatif().
Une seule responsabilité
Si tu dois écrire « et » pour décrire ce que fait ta fonction, elle en fait probablement trop. Découpe.
Courte
Au-delà d'une vingtaine de lignes, on ne la tient plus en tête. Ce n'est pas une règle absolue, mais un signal.
Le principe DRY
Don't Repeat Yourself. Si tu copies-colles un bloc pour la deuxième fois, c'est le moment d'en faire une fonction — sinon la troisième correction de bug devra être faite à trois endroits.
Documenter avec une docstring
python
def pgcd(a, b):
"""Renvoie le plus grand commun diviseur de a et b.
Utilise l'algorithme d'Euclide : tant que b n'est pas nul,
on remplace (a, b) par (b, a % b).
"""
while b != 0:
a, b = b, a % b
return a
print(pgcd(12, 18))
Résultat : 6

Une chaîne placée juste après la ligne def devient la DOCSTRING de la fonction. Ce n'est pas un commentaire ordinaire : sur un Python installé, l'interpréteur la garde en mémoire — help(pgcd) l'affiche, et les outils de documentation la lisent. C'est la convention pour expliquer ce qu'une fonction attend et ce qu'elle renvoie.

Découpe un programme

Le même travail, mais réparti en fonctions qui se comprennent chacune isolément.

Chargement de l'éditeur Python…

À retenir

  • def définit, nom() appelle. Il faut définir avant d'appeler.
  • print AFFICHE pour un humain ; return DONNE une valeur au programme. Une fonction calcule et renvoie.
  • Sans return, une fonction renvoie None — d'où les « None » inattendus.
  • return arrête la fonction immédiatement : place-le après la boucle si tu accumules.
  • Les paramètres peuvent avoir une valeur par défaut, et les arguments peuvent être nommés à l'appel.
  • Une variable créée dans une fonction est LOCALE ; fais circuler l'information par paramètres et return.
  • On peut renvoyer plusieurs valeurs : return a, b puis x, y = f().
  • Un bon nom, une seule responsabilité, une docstring — et jamais deux fois le même bloc de code.
Mots-clésfonctiondefreturnparamètreargumentportéedocstringDRY