Les fonctions
Informatique — Python, chapitre 6
Un calcul écrit trois fois dans un script devra être corrigé trois fois. Écrit une fois dans une fonction, il se corrige en un seul endroit et s’appelle partout.
La fonction n’est pas seulement une commodité : c’est l’outil qui permet de découper un problème en morceaux compréhensibles séparément. C’est le chapitre qui sépare l’usage occasionnel du langage de sa pratique sérieuse.
6.1 Définir et appeler
6.1.1 La forme minimale
def déclare, les parenthèses listent les paramètres, les deux points et l’indentation délimitent le corps, et return renvoie le résultat.
6.1.2 return n’est pas print
print affiche à l’écran. return renvoie une valeur utilisable.
Une fonction sans return renvoie None. Le résultat s’affiche donc bien lors de l’appel, mais il est impossible de le réutiliser : ni de le stocker, ni de le sommer, ni de le passer à une autre fonction.
Une fonction de calcul doit toujours renvoyer. Réservez print à l’affichage final.
6.1.3 return interrompt la fonction
Dès qu’un return s’exécute, la fonction s’arrête. On peut donc en placer plusieurs, sans else — une écriture souvent plus lisible que les branches imbriquées.
6.1.4 Renvoyer plusieurs valeurs
Python renvoie en réalité un tuple, que l’affectation multiple du chapitre 3 décompose aussitôt. C’est bien plus commode que dans la plupart des langages.
6.2 Les arguments
6.2.1 Position ou nom
Nommer les arguments rend l’appel auto-documenté. Sur une fonction à cinq paramètres, c’est indispensable.
6.2.2 Les valeurs par défaut
Les paramètres sans défaut d’abord, ceux avec défaut ensuite. L’inverse provoque une erreur de syntaxe.
def ajouter(x, liste=[]): # PIEGE
liste.append(x)
return liste
print(ajouter(1)) # [1]
print(ajouter(2)) # [1, 2] au lieu de [2] !La valeur par défaut est créée une seule fois, à la définition de la fonction, et non à chaque appel. La même liste est donc réutilisée et s’accumule.
La parade est un idiome à connaître :
def ajouter(x, liste=None):
if liste is None:
liste = []
liste.append(x)
return listeCe piège figure dans tous les entretiens d’embauche Python, parce qu’il révèle si l’on a compris quand le code est évalué.
6.3 La portée des variables
Une variable créée dans une fonction est locale : elle disparaît à la sortie. C’est une garantie : appeler une fonction ne peut pas modifier vos variables à votre insu.
La fonction ci-dessus fonctionne… tant que seuil existe. Copiée dans un autre script, elle échoue ou, pire, utilise un autre seuil sans le signaler.
Écrivez plutôt :
def teste(x, seuil=10):
return x > seuilTout ce dont la fonction a besoin doit entrer par la porte. C’est la règle qui rend une fonction testable, réutilisable et déplaçable.
6.3.1 L’exception des objets modifiables
Un nombre ou une chaîne passés à une fonction sont protégés. Une liste ne l’est pas : la fonction reçoit une référence au même objet, comme lors de la copie du chapitre 3.
Si vous ne voulez pas modifier l’original, copiez en entrant : liste = liste.copy().
6.4 Documenter
La docstring est une chaîne en triple guillemets placée juste après le def. Elle n’est pas un commentaire : Python la conserve, help() l’affiche, et les éditeurs la montrent au survol.
Prenez l’habitude d’en écrire une dès que la fonction dépasse trois lignes. Le premier lecteur de votre code sera vous-même, dans six mois.
6.5 Les fonctions anonymes
lambda définit une fonction d’une seule expression, sans nom. Son usage légitime est celui-ci : passer un petit critère à sorted, map ou filter.
carre = lambda x: x ** 2 # deconseille
def carre(x): return x ** 2 # preferableSi vous donnez un nom à la fonction, autant utiliser def : le message d’erreur sera plus clair, et une docstring devient possible.
lambda est fait pour les fonctions qu’on écrit à l’endroit où on les utilise, et nulle part ailleurs.
6.6 Un exemple complet
Trois fonctions courtes valent mieux qu’une longue : chacune fait une chose, se teste seule, et ecart_type réutilise moyenne sans la réécrire.
Notez if not v: return None : la protection contre la liste vide, écrite avec l’idiome du chapitre 5.
À vous
Écrivez une fonction mention qui renvoie la mention correspondant à une note, avec un seuil de réussite paramétrable, puis appliquez-la à une liste.
def mention(note, seuil=10):
"""Renvoie la mention d'une note, selon un seuil de reussite."""
if note >= 16:
return "tres bien"
if note >= 14:
return "bien"
if note >= seuil:
return "passable"
return "insuffisant"
for n in notes:
print(f"{n:>3} : {mention(n)}")
# avec un seuil different
print([mention(n, seuil=12) for n in notes])Les return successifs sans else — l’écriture vue en 6.1.3 — évitent quatre niveaux d’imbrication. Et le paramètre seuil rend la fonction réutilisable pour un autre barème.
Ce qu’il faut retenir
| Écriture | Effet |
|---|---|
def f(x): |
définir une fonction |
return |
renvoyer une valeur — jamais confondre avec print |
plusieurs return |
le premier exécuté arrête la fonction |
return a, b, c |
renvoyer plusieurs valeurs (un tuple) |
f(debut=100) |
appeler en nommant les arguments |
def f(x, n=1) |
valeur par défaut — sans défaut d’abord |
def f(x, liste=None) |
jamais une liste comme valeur par défaut |
| variable locale | disparaît à la sortie de la fonction |
| liste passée en argument | peut être modifiée — copiez si besoin |
"""...""" |
docstring, affichée par help() |
lambda x: x ** 2 |
fonction anonyme, pour sorted(key=...) |
Le chapitre suivant clôt la première partie avec deux outils indispensables au travail réel : les dictionnaires et la lecture de fichiers.