Les fonctions sont l’outil #1 pour organiser et réutiliser son code. Au niveau Basique, on utilisait des fonctions natives (len, sum, sorted…). Au niveau Opérationnel, vous allez créer les vôtres. C’est la différence entre « savoir utiliser Python » et « coder en Python ».
20.1 Pourquoi des fonctions ?
Imaginez devoir calculer la moyenne de 3 listes de notes différentes. Sans fonction :
def additionner(a, b): resultat = a + bprint(resultat)additionner(3, 5)additionner(10, 20)
8
30
Vocabulaire précis : paramètre vs argument
Terme
Signification
Paramètre
Variable définie dans la signature de la fonction (def f(x):)
Argument
Valeur réellement passée lors de l’appel (f(5))
def multiplier(a, b): # a et b sont des paramètresreturn a * br = multiplier(3, 5) # 3 et 5 sont des arguments
C’est un détail, mais le TOSA peut tester le vocabulaire.
20.4 L’instruction return
returnrenvoie une valeur à l’appelant et sort immédiatement de la fonction.
def carre(x):return x * xr = carre(5)print(r)print(carre(10) + carre(3))
25
109
Différence fondamentale entre print et return
⚠️ Piège TOSA très classique
printaffiche à l’écran ; returnrenvoie une valeur exploitable.
def afficher(x):print(x *2) # print, pas returndef calculer(x):return x *2# return, pas printa = afficher(5) # affiche 10, mais a vaut None !b = calculer(5) # n'affiche rien, mais b vaut 10print("a =", a)print("b =", b)
10
a = None
b = 10
Question TOSA type : « Que renvoie afficher(5) ? » → None (pas 10 !).
Une fonction peut avoir plusieurs return
Utile pour les conditions :
def valeur_absolue(x):if x >=0:return xelse:return-xprint(valeur_absolue(5))print(valeur_absolue(-7))
5
7
Une fonction peut ne rien returner
Dans ce cas, elle renvoie implicitement None :
def bonjour(nom):print("Bonjour", nom)# pas de returnresultat = bonjour("Alice")print("resultat =", resultat) # None
Bonjour Alice
resultat = None
Retour multiple (tuple implicite)
On peut renvoyer plusieurs valeurs séparées par des virgules — c’est en fait un tuple.
On peut donner une valeur par défaut à un paramètre. L’appelant peut alors l’omettre.
def saluer(prenom, politesse="Bonjour"):print(f"{politesse}, {prenom} !")saluer("Alice") # utilise la valeur par défautsaluer("Bob", "Salut") # remplace la valeur par défaut
Bonjour, Alice !
Salut, Bob !
Règle de placement
Les paramètres avec valeur par défaut doivent venir après les paramètres sans défaut dans la signature.
# ❌ Erreur : on ne peut pas avoir "b" obligatoire après "a" optionneldef f(a=1, b):pass
CellIn[14], line 2def f(a=1, b):
^
SyntaxError: parameter without a default follows parameter with a default
# ✅ Ordre correctdef f(a, b=1):pass
⚠️ Piège TOSA majeur : valeurs par défaut MUTABLES
N’utilisez JAMAIS une liste, un dict ou un set comme valeur par défaut !
Le défaut [] est créé une seule fois à la définition, puis partagé entre tous les appels. La bonne pratique :
# ✅ Pattern correctdef ajouter(element, liste=None):if liste isNone: liste = [] liste.append(element)return listeprint(ajouter("a"))print(ajouter("b")) # liste neuve à chaque appel
['a']
['b']
Ce piège est très testé au TOSA Avancé. Nous le reverrons au chapitre 5.
20.6 Les arguments nommés (keyword arguments)
À l’appel, on peut passer les arguments par position ou par nom :
def saluer(prenom, politesse="Bonjour", ponctuation="!"):print(f"{politesse}{prenom}{ponctuation}")# Par positionsaluer("Alice")# Par nom (keyword argument)saluer(prenom="Alice", politesse="Salut")# Par nom, on peut changer l'ordre !saluer(politesse="Hello", prenom="Bob")# Mélange possible : positionnels d'abord, puis nomméssaluer("Charlie", ponctuation="?")
Quand un appel a beaucoup de paramètres et qu’on veut être explicite.
Quand on veut sauter un paramètre optionnel au milieu.
Pour améliorer la lisibilité :
# ❌ Peu clair à la lecturecreer_utilisateur("Alice", 30, True, False)# ✅ Bien plus claircreer_utilisateur(nom="Alice", age=30, actif=True, admin=False)
20.7 La portée des variables (scope)
La portée (scope) détermine où une variable est accessible.
Variable locale
Une variable définie dans une fonction est locale à cette fonction. Elle n’existe pas à l’extérieur.
def f(): x =10# locale à fprint("Dans f : x =", x)f()
Dans f : x = 10
def f(): x =10f()print(x) # ❌ NameError : x n'existe pas ici
---------------------------------------------------------------------------NameError Traceback (most recent call last)
CellIn[19], line 5 1def f():
2 x = 10 3 4 f()
----> 5 print(x) # ❌ NameError : x n'existe pas iciNameError: name 'x' is not defined
Variable globale
Une variable définie à l’extérieur d’une fonction est globale — accessible en lecture depuis une fonction.
message ="Bonjour !"# globaledef afficher():print(message) # on peut LIRE la globaleafficher()
Bonjour !
⚠️ Modifier une globale depuis une fonction
Par défaut, impossible. Python crée une nouvelle variable locale :
Pour vraiment modifier la globale, il faut le déclarer explicitement avec global — mais c’est rarement souhaitable.
compteur =0def increment():global compteur # on DIT qu'on modifie la globale compteur +=1increment()increment()print(compteur)
2
Bonne pratique : évitez les globales modifiées. Passez la valeur en paramètre et retournez-en une nouvelle :
def incrementer(c):return c +1compteur =0compteur = incrementer(compteur)compteur = incrementer(compteur)print(compteur)
2
20.8 Fonction vs procédure
Certains langages distinguent fonction (renvoie une valeur) et procédure (sans retour). Python ne fait pas cette distinction — tout est une fonction. Une fonction sans return renvoie implicitement None.
def afficher(x): # "procédure" — pas de returnprint(x)def doubler(x): # "fonction" — renvoie une valeurreturn2* xprint(afficher(5)) # affiche 5 puis Noneprint(doubler(5)) # affiche 10
5
None
10
20.9 Conventions de nommage (PEP 8)
Noms en snake_case : mots en minuscules séparés par _.
Verbes d’action pour décrire ce que fait la fonction.
Nom descriptif même au prix de quelques caractères.
# ✅ Bons nomsdef calculer_moyenne(notes): ...def est_majeur(age): ...def envoyer_email(destinataire, sujet): ...# ❌ À éviterdef calcMoy(n): ... # camelCase, cryptiquedef f(x): ... # nom non parlantdef CALCULER(x): ... # RÉSERVÉ AUX CONSTANTES
🧩 Quiz 1.1 — Les fonctions
Question 1
Que renvoie f(5) pour cette fonction ?
def f(x): x *2
10
5
None
Une erreur
🔍 Réponse
c) None — piège classique ! La ligne x * 2calcule mais ne renvoie rien (pas de return). La fonction renvoie donc None par défaut.
print affiche, return renvoie une valeur utilisable
Une fonction doit toujours avoir un return
return peut apparaître plusieurs fois dans une fonction, mais seul le premier est exécuté par appel
🔍 Réponse
b) et d) sont vraies. Mais la plus précise est d) : on peut avoir plusieurs return, mais dès qu’un est atteint, la fonction sort. Les autres ne sont pas exécutés pour cet appel.
def signe(x):if x >0:return"positif"elif x <0:return"négatif"return"nul"# atteint seulement si x == 0print(signe(5), signe(-3), signe(0))
positif négatif nul
Question 4
Que s’affiche-t-il ?
x =10def f(): x =20print(x)f()print(x)
20 puis 20
20 puis 10
10 puis 20
10 puis 10
🔍 Réponse
b) 20 puis 10 — dans f(), on crée une variable locale x qui n’a rien à voir avec la globale. La globale reste à 10.
x =10def f(): x =20print(x)f()print(x)
20
10
Question 5
Quelle définition est invalide ?
def f(a, b=1):
def f(a=1, b=2):
def f(a=1, b):
def f(a, b):
🔍 Réponse
c) def f(a=1, b): — les paramètres avec défaut doivent venir après les paramètres sans défaut.
def f(a=1, b):pass
CellIn[29], line 1def f(a=1, b):
^
SyntaxError: parameter without a default follows parameter with a default
Règle : ne jamais utiliser une liste (ou dict/set) comme valeur par défaut. Utilisez None et testez.
✏️ Exercice 1.1 — Fonction de conversion
Écrivez une fonction celsius_vers_fahrenheit(c) qui convertit une température de Celsius en Fahrenheit, sachant que F = C × 9/5 + 32. Testez-la avec plusieurs valeurs.
Écrivez une fonction est_majeur(age, age_legal=18) qui renvoie True si age >= age_legal, False sinon. Le deuxième paramètre permet de tester d’autres âges légaux (21 aux États-Unis par exemple).
Écrivez une fonction compter_mots(texte) qui renvoie un dictionnaire avec le nombre d’occurrences de chaque mot (insensible à la casse et à la ponctuation simple).
Exemple : compter_mots("Le chat et le chien") → {"le": 2, "chat": 1, "et": 1, "chien": 1}.
def compter_mots(texte): ...print(compter_mots("Le chat et le chien"))print(compter_mots("Python est un langage. Python est populaire."))
def compter_mots(texte):# Normaliser : minuscules et retirer la ponctuation simplefor char in".,;:!?": texte = texte.replace(char, "") mots = texte.lower().split() occurrences = {}for mot in mots: occurrences[mot] = occurrences.get(mot, 0) +1return occurrencesprint(compter_mots("Le chat et le chien"))print(compter_mots("Python est un langage. Python est populaire."))
Écrivez une fonction encadrer(mot, caractere="*") qui renvoie le mot entouré de caractères. Exemple : encadrer("TOSA") → "*** TOSA ***" (3 étoiles de chaque côté).