1.4Fonctions, arguments & portée
L'essentiel en 30 secondes
- Fonction = un travail, un nom verbe : def calculer_tva(prix_ht): + return — afficher (print) n'est pas renvoyer.
- Défauts immuables : def f(items=None) puis création dedans — jamais def f(items=[]) qui survit entre appels.
- Locale d'abord, globale jamais : données en arguments, résultat par return — *args/**kwargs pour la flexibilité.
Mini-cas filé — Nabil factorise ses calculs à Alger
Nabil calcule la moyenne des scores à quatre endroits de son script avec le même copier-coller — et quand la règle change (ignorer les zéros), il oublie deux endroits : un rapport sur quatre est faux. Il crée une fonction moyenne(*notes) qui reçoit tout en paramètres et renvoie le résultat : un seul endroit à corriger. Au passage, il corrige un def ajouter(x, items=[]) qui accumulait entre appels (None + création dedans) et remplace un print par un return. Les quatre rapports redeviennent justes d'un coup.
Suite du cas 1.1-1.3 — Nabil passe de la répétition à la réutilisation.
1. Une fonction = un travail, un nom verbe
Une fonction est un bloc nommé et réutilisable : def calculer_tva(prix_ht): — nom verbe + snake_case, une responsabilité, return le résultat. Sans return, la fonction renvoie None : print affiche, return transmet — le print ne remplace pas le return. C'est le principe DRY (ne vous répétez pas).
Nabil remplace ses quatre copier-coller de moyenne par moyenne(*notes) : un seul endroit à corriger quand la règle change, quatre rapports justes.
2. Arguments, défauts et portée
Les paramètres sont déclarés dans la définition, les arguments passés à l'appel ; les défauts viennent après les obligatoires (def saluer(nom, politesse="Bonjour")). Piège célèbre : def f(items=[]) — la liste survit entre appels, écrire def f(items=None). *args collecte des valeurs, **kwargs des paires nom=valeur. Portée : une variable créée dans la fonction est locale (NameError dehors) — passer par arguments, récupérer par return.
Nabil corrige son défaut mutable en None, ajoute moyenne(*notes) pour 2 puis 5 notes, et constate la NameError d'une variable locale accédée dehors : local contre global, tranché.
🔎 Exemple concret — 🔎 Exemple concret — Le piège de la liste par défaut
Le bug célèbre, comme Nabil sur ses moyennes.
def ajouter(x, items=None):
items = items if items is not None else []
items.append(x)
return items
print(ajouter(1)) # [1]
print(ajouter(2)) # [2] : plus de surprise
def moyenne(*notes):
return sum(notes) / len(notes)
print(moyenne(12, 15, 9))
Lecture : le défaut mutable est créé une seule fois — None + création dedans l'évite.
Leçon : *args collecte un nombre variable d'arguments ; return rend le résultat réutilisable.
Vocabulaire de la section
- Fonction / def
- Bloc de code nommé et réutilisable, défini avec def nom(paramètres):. Appelé par nom(arguments). Nom verbe, une responsabilité (DRY).
Exemple simple : La moyenne(*notes) unique de Nabil, appelée quatre fois.
Ce que ce n'est pas : le même calcul copié-collé à quatre endroits.
Réflexe : calcul répété deux fois = fonction.
- Paramètre / argument
- Le paramètre est la variable déclarée dans la définition ; l'argument est la valeur réelle passée à l'appel. Les défauts viennent après les obligatoires.
Exemple simple : Le politesse="Bonjour" de saluer(nom) chez Nabil.
Ce que ce n'est pas : un défaut mutable [] partagé entre appels.
Réflexe : défauts immuables (None), jamais [] ou {}.
- return
- Renvoie une valeur en sortie de la fonction et met fin à son exécution. Sans return, la fonction renvoie None. print affiche, return transmet.
Exemple simple : La moyenne renvoyée par Nabil, stockée puis affichée.
Ce que ce n'est pas : une fonction qui print sans return, inutilisable en calcul.
Réflexe : résultat à réutiliser = return, toujours.
- Portée (scope)
- Zone de visibilité d'une variable. Une variable créée dans une fonction est locale : elle n'existe pas à l'extérieur (NameError).
Exemple simple : La variable locale de Nabil, inaccessible dehors.
Ce que ce n'est pas : modifier une globale avec global au lieu d'un paramètre.
Réflexe : besoin d'une donnée ? paramètre ; besoin du résultat ? return.
- *args / **kwargs
- Permettent de recevoir un nombre variable d'arguments : *args (tuple de valeurs), **kwargs (dictionnaire de paires nom=valeur).
Exemple simple : La moyenne(*notes) de Nabil avec 2 puis 5 notes.
Ce que ce n'est pas : cinq paramètres optionnels à rallonge au lieu de *args.
Réflexe : nombre inconnu = *args ; options nommées = **kwargs.
En pratique — En pratique — Définir et appeler des fonctions
- Écrivez une fonction saluer(nom) qui renvoie (return) « Bonjour, {nom} ! ». Appelez-la avec différents noms et affichez le résultat.
- Ajoutez un paramètre par défaut : saluer(nom, politesse="Bonjour"). Appelez-la avec et sans le second argument.
- Écrivez une fonction moyenne(*notes) qui accepte un nombre variable de notes et renvoie leur moyenne. Testez avec 2, puis 5 notes.
- Illustrez la portée : créez une variable dans une fonction et tentez d'y accéder à l'extérieur (NameError). Concluez sur local vs global.
Script prêt à dire — refuser le print au lieu du return (30 s)
« Je propose que cette fonction renvoie le résultat avec return plutôt que de l'afficher : comme ça on peut le stocker, le tester et le réutiliser. Le print ne transmet rien — l'appel vaut None et le calcul d'après plante. »
À dire en revue de code ; montrer l'appel stocké avant/après.
Modèle copier-coller — fonctions saines (return, défaut sûr, *args)
def saluer(nom, politesse="Bonjour"):
return f"{politesse}, {nom} !"
print(saluer("Nabil"))
print(saluer("Yasmine", politesse="Salut"))
def moyenne(*notes):
return sum(notes) / len(notes)
print(moyenne(12, 15))
print(moyenne(10, 14, 16, 8, 12))
def ajouter(x, items=None):
items = items if items is not None else []
items.append(x)
return items
Moyennes à Alger
Comme Nabil : une seule fonction moyenne(*notes) — la règle change une fois, quatre rapports justes.
Donnée externe à utiliser
La passer en paramètre explicite : la signature documente le besoin, la fonction reste testable isolément.
Valeur par défaut
Le politesse="Bonjour" en défaut : l'appel simple couvre le cas courant, l'appel complet le cas particulier.
Nombre variable
*notes pour 2 puis 5 notes, **options pour les réglages nommés : la signature reste courte et flexible.
✓ Bonnes pratiques
- Un verbe, un travail, un return — jamais de print à la place.
- Défauts immuables (None, pas [] ni {}).
- Données en arguments, jamais en global.
✗ Pièges fréquents
- Faire print au lieu de return (appel qui vaut None).
- Écrire un défaut mutable ([] ou {}) qui survit entre appels.
- Utiliser global pour modifier dehors au lieu d'un paramètre.
Points clés à retenir
- Une fonction (def) regroupe un code réutilisable : principe DRY — nom verbe, une responsabilité.
- return renvoie un résultat réutilisable ; sans lui, la fonction renvoie None (print ne remplace pas return).
- Arguments par défaut, *args et **kwargs offrent de la flexibilité — défauts immuables uniquement.
- Une variable définie dans une fonction est locale : invisible à l'extérieur — arguments en entrée, return en sortie.
Défi 48h — appliquez demain
Extrayez un calcul dupliqué de votre script en fonction (modèle ci-dessus) : paramètres explicites, return, défaut sûr. Remplacez un print par un return et testez avec 2 puis 5 arguments. 25 minutes suffisent.
- Je définis des fonctions avec paramètres, défaut sûr, return et *args.
- Je respecte la portée locale — aucune globale modifiée.
- Je distingue print (afficher) de return (transmettre).
Questions fréquentes
Quelle différence entre print() et return dans une fonction ?
print() affiche à l'écran mais ne transmet rien au reste du programme. return renvoie une valeur exploitable (stockable, calculable). Une fonction qui « print » sans « return » ne sert qu'à afficher ; pour réutiliser le résultat, il faut return — sinon l'appel vaut None.
À quoi servent *args et **kwargs concrètement ?
Ils rendent une fonction flexible sur le nombre d'arguments. *args collecte des valeurs positionnelles en tuple (utile pour une moyenne d'un nombre inconnu de notes) ; **kwargs collecte des paires clé=valeur en dictionnaire (utile pour des options nommées comme sep, titre...).
Que vaut l'appel d'une fonction sans return ?