Aller au contenu

Fonctions

Les fonctions sont le cœur de la programmation structurée : elles permettent de découper un problème en petits morceaux réutilisables, lisibles et testables.


Introduction

Imaginons que vous deviez calculer l'aire d'un rectangle à plusieurs endroits de votre programme :

aire1 = 5 * 3
aire2 = 8 * 4
aire3 = 12 * 6

Cela fonctionne, mais le jour où la formule change (par exemple pour gérer les décimales), vous devrez modifier chaque ligne… et risquer d'en oublier une.

Une fonction regroupe cette logique en un seul endroit :

def aire_rectangle(longueur, largeur):
    return longueur * largeur

À retenir

Une fonction est un bloc de code nommé et réutilisable. On la définit une fois, puis on l'appelle autant de fois que nécessaire.


Définir une fonction

La syntaxe commence par le mot-clé def, suivi du nom de la fonction, de parenthèses et d'un deux-points :

def dire_bonjour():
    print("Bonjour !")
  • Le corps de la fonction (les instructions indentées) ne s'exécute que lorsqu'on appelle la fonction.
  • La fonction peut recevoir des paramètres entre parenthèses (voir plus bas).
def saluer(nom):
    print(f"Salut {nom} !")

Important

Tant que vous ne l'appelez pas, la fonction ne fait rien. La définir ne suffit pas.


Appeler une fonction

Pour exécuter une fonction, on écrit son nom suivi de parenthèses :

def saluer(nom):
    print(f"Salut {nom} !")

saluer("Alex")      # Salut Alex !
saluer("Sam")       # Salut Sam !

L'appel peut se faire autant de fois qu'on veut, avec des valeurs différentes. C'est tout l'intérêt de la réutilisation.


Paramètres et arguments

Il existe une nuance de vocabulaire importante :

  • Paramètre : la variable déclarée dans la définition de la fonction (nom dans saluer(nom)).
  • Argument : la valeur réelle fournie à l'appel ("Alex" dans saluer("Alex")).
def addition(a, b):      # a et b sont des PARAMÈTRES
    print(a + b)

addition(3, 5)           # 3 et 5 sont des ARGUMENTS
addition(10, 2)

Une fonction peut avoir autant de paramètres que nécessaire :

def profil(nom, age, ville):
    print(f"{nom}, {age} ans, habite à {ville}")

profil("Alex", 25, "Paris")
profil("Sam", 30, "Lyon")

Bonnes pratiques

  • Choisissez des noms de paramètres explicites (longueur, largeur) plutôt que a, b quand c'est possible.
  • Un nom de fonction commence par une minuscule et décrit l'action (calculer_total, afficher_menu).

Valeur de retour

Une fonction ne se contente pas d'afficher : elle peut renvoyer une valeur avec le mot-clé return. Cette valeur peut ensuite être stockée dans une variable ou utilisée dans une expression :

def carre(nombre):
    return nombre ** 2

resultat = carre(5)
print(resultat)          # 25
print(carre(7))          # 49
def addition(a, b):
    return a + b

total = addition(3, 5) + addition(1, 1)
print(total)             # 10

Sans return explicite, une fonction renvoie None (l'absence de valeur) :

def afficher(message):
    print(message)

resultat = afficher("coucou")   # affiche : coucou
print(resultat)                 # None

Attention

print() affiche à l'écran, return fournit une valeur au programme. Ce sont deux choses différentes - souvent confondues par les débutants.


Arguments par défaut

Un paramètre peut avoir une valeur par défaut. Si l'argument est omis à l'appel, c'est cette valeur qui sera utilisée :

def saluer(nom, ponctuation="!"):
    print(f"Salut {nom}{ponctuation}")

saluer("Alex")            # Salut Alex!
saluer("Alex", " ?")      # Salut Alex ?

Règle

Les paramètres avec valeurs par défaut doivent être placés après les paramètres sans valeur par défaut :

def exemple(a, b=0):   # ✅ correct
    pass

# def exemple(a=0, b):  # ❌ erreur de syntaxe

Arguments nommés

On peut appeler une fonction en précisant le nom des paramètres - l'ordre n'a alors plus d'importance :

def profil(nom, age, ville):
    print(f"{nom}, {age} ans, {ville}")

profil(age=25, ville="Paris", nom="Alex")   # ✅ ordre libre

C'est particulièrement utile pour les fonctions avec beaucoup de paramètres : le code est plus lisible et on évite les erreurs d'ordre.

def creer_compte(pseudo, email, 
                 notification_ok=True, mode_sombre=False):
    print(f"Compte {pseudo} créé ({email})")
    print(f"Notifications : {notification_ok}, thème sombre : {mode_sombre}")

creer_compte("alex42", "alex@mail.com")
creer_compte("sam", "sam@mail.com", mode_sombre=True)

Portée des variables

Une variable définie à l'intérieur d'une fonction est locale : elle n'existe que dans la fonction.

def calculer():
    x = 10          # variable locale
    print(x)        # 10

calculer()
# print(x)          # ❌ NameError : x n'existe pas ici

Une variable définie hors de toute fonction est globale : elle est lisible dans la fonction, mais non modifiable directement.

compteur = 0        # variable globale

def afficher_compteur():
    print(compteur)     # ✅ lecture OK

afficher_compteur()     # 0
compteur = 0

def incrementer():
    compteur = compteur + 1   # ❌ UnboundLocalError !

incrementer()

Pour modifier une variable globale depuis une fonction, on utilise le mot-clé global :

compteur = 0

def incrementer():
    global compteur
    compteur = compteur + 1

incrementer()
incrementer()
print(compteur)          # 2

Conseil

Privilégiez la valeur de retour plutôt que global : passer par des paramètres et un return rend les fonctions prévisibles et faciles à tester.

def incrementer(valeur):
    return valeur + 1

compteur = 0
compteur = incrementer(compteur)
compteur = incrementer(compteur)
print(compteur)          # 2 - même résultat, sans effet global

Docstrings

Une docstring est une chaîne de caractères documentant le rôle de la fonction, placée juste après def :

def aire_rectangle(longueur, largeur):
    """Calcule l'aire d'un rectangle."""
    return longueur * largeur

On peut la consulter avec help() :

help(aire_rectangle)

À savoir

Multi-lignes : description, paramètres, valeur de retour.

def diviser(a, b):
    """
    Divise deux nombres.

    Paramètres :
        a (float) : le dividende.
        b (float) : le diviseur.

    Retourne :
        float : le quotient de a par b.
    """
    return a / b

Bonnes pratiques

Règle Exemple
Un nom explicite def calculer_moyenne(...) plutôt que def m(...)
Une fonction = une tâche def valider_email(...) puis def envoyer_email(...)
Garder le code court si la fonction dépasse 20 lignes, découper
Éviter les variables globales utiliser des paramètres + return
Documenter avec une docstring """Résumé de ce que fait la fonction."""

Exemples pratiques

Énoncé

Écrire une fonction est_pair(nombre) qui renvoie True si le nombre est pair, False sinon.

Solution
def est_pair(nombre):
    return nombre % 2 == 0

print(est_pair(4))     # True
print(est_pair(7))     # False

Énoncé

Écrire une fonction moyenne(nombres) qui reçoit une liste et renvoie sa moyenne.

Solution
def moyenne(nombres):
    if len(nombres) == 0:
        return 0
    return sum(nombres) / len(nombres)

print(moyenne([15, 18, 12]))    # 15.0

Énoncé

Écrire une fonction convertir_temperature(celsius) qui convertit en Fahrenheit, puis l'utiliser pour afficher plusieurs valeurs.

Solution
def convertir_temperature(celsius):
    return celsius * 9 / 5 + 32

for temp in [0, 25, 100]:
    print(f"{temp}°C = {convertir_temperature(temp)}°F")

Résumé

Mot-clé / Notion Rôle
def nom(...) Définir une fonction
nom(argument) Appeler une fonction
return valeur Renvoyer une valeur
None Valeur renvoyée par défaut (pas de return)
Paramètres / Arguments Variables définies / valeurs fournies à l'appel
Valeur par défaut def f(x, y=0) - argument optionnel
Arguments nommés f(y=2, x=1) - ordre libre
Variable locale / globale Interne à la fonction / accessible partout
Docstring Documentation de la fonction