🎭python

Les decorateurs Python expliques simplement

30 mars 2026 5 min de lecture

Introduction : La magie du @ en Python

Si tu as déjà croisé un étrange symbole @ au-dessus d'une fonction en Python et que tu t'es demandé à quoi il servait, tu es au bon endroit. Ce symbole, c'est celui d'un décorateur (ou decorator en anglais). C'est l'un des concepts les plus élégants et puissants de Python, mais aussi l'un de ceux qui peuvent sembler un peu mystérieux au premier abord. Pas de panique ! Dans cet article, on va démystifier tout ça ensemble, étape par étape. Tu vas voir qu'une fois le principe compris, les décorateurs deviennent un outil incroyable pour écrire un code plus propre, plus modulaire et plus professionnel. C'est exactement le genre de compétence qui fait la différence en NSI et dans tes futurs projets.

Les fonctions : des citoyens de première classe

Pour comprendre les décorateurs, il faut d'abord bien saisir un concept fondamental en Python : les fonctions sont des objets de première classe. Qu'est-ce que ça veut dire ? Tout simplement que tu peux :

  • Assigner une fonction à une variable.
  • Passer une fonction en argument à une autre fonction.
  • Retourner une fonction depuis une autre fonction.

Regarde cet exemple simple :

def dire_bonjour(nom):
return f"Bonjour {nom}!"

# 1. Assignation à une variable
ma_fonction = dire_bonjour
print(ma_fonction("Alice")) # Affiche : Bonjour Alice!

# 2. Passage en argument
def appliquer_deux_fois(f, valeur):
return f(f(valeur))

# 3. Retour d'une fonction
def creer_multiplicateur(facteur):
def multiplier(n):
return n * facteur
return multiplier

Cette flexibilité est le socle sur lequel reposent les décorateurs. Une fonction qui en prend une autre en argument et qui en retourne une nouvelle modifiée, c'est exactement le principe de base d'un décorateur !

Construire son premier décorateur pas à pas

Imaginons que tu as une fonction qui fait un calcul et que tu veux chronométrer son temps d'exécution. Tu pourrais modifier le code de la fonction pour ajouter un chronomètre... mais c'est pénible et tu mélangerais la logique du calcul avec celle de la mesure. C'est là que le décorateur entre en jeu !

On va créer un décorateur chronometrer :

import time

# 1. Notre futur décorateur est une fonction qui prend une fonction en argument.
def mon_decorateur(fonction_a_decorer):
# 2. À l'intérieur, on définit une NOUVELLE fonction (la "wrapper").
def fonction_modifiee():
print("Début de l'exécution...")
resultat = fonction_a_decorer() # On appelle la fonction originale
print("Fin de l'exécution !")
return resultat
# 3. On retourne cette nouvelle fonction.
return fonction_modifiee

# Une fonction simple
def ma_tache():
print("Je fais mon travail.")

# 4. Application "manuelle" du décorateur
ma_tache_decoree = mon_decorateur(ma_tache)
ma_tache_decoree() # Affiche : Début... / Je fais... / Fin !

Félicitations, tu viens de créer ton premier décorateur ! La syntaxe @ n'est qu'un sucre syntaxique (une façon plus jolie d'écrire) pour faire exactement cette opération. Au lieu des lignes 4 ci-dessus, on écrit simplement :

@mon_decorateur
def ma_tache():
print("Je fais mon travail.")

# Maintenant, quand on appelle ma_tache(), elle est automatiquement décorée.
ma_tache()

Beaucoup plus propre, non ? Le décorateur a enveloppé ta fonction originale pour lui ajouter un comportement avant et après son exécution, sans que tu aies à toucher à son code.

Décorateurs utiles pour tes projets NSI

Maintenant que tu maîtrises le principe, voyons des applications concrètes qui vont booster tes projets.

1. Le décorateur de logging (journalisation)

Parfait pour déboguer ou suivre l'activité d'un programme.

def logger(fonction):
def wrapper(*args, **kwargs):
print(f"[LOG] Appel de {fonction.__name__} avec args={args}, kwargs={kwargs}")
resultat = fonction(*args, **kwargs)
print(f"[LOG] {fonction.__name__} a retourné : {resultat}")
return resultat
return wrapper

@logger
def addition(a, b):
return a + b

addition(5, 3) # Affiche les logs automatiquement.

2. Le décorateur de validation des arguments

Assure-toi que les arguments passés à une fonction sont valides.

def valider_positif(fonction):
def wrapper(n):
if n <= 0:
raise ValueError("L'argument doit être positif !")
return fonction(n)
return wrapper

@valider_positif
def racine_carree(n):
return n ** 0.5

print(racine_carree(9)) # 3.0
# print(racine_carree(-4)) # Lève une ValueError !

3. Le décorateur de mise en cache (mémoïsation)

Un classique pour optimiser les fonctions récursives coûteuses, comme la suite de Fibonacci.

def memoisation(fonction):
cache = {} # Dictionnaire pour stocker les résultats déjà calculés
def wrapper(n):
if n not in cache:
cache[n] = fonction(n)
return cache[n]
return wrapper

@memoisation
def fibo(n):
if n <= 1:
return n
return fibo(n-1) + fibo(n-2)

print(fibo(50)) # Calcul ultra-rapide grâce au cache !

Ces exemples montrent la puissance des décorateurs : ils te permettent d'ajouter des fonctionnalités transversales (logging, validation, cache) de manière non intrusive et réutilisable.

Aller plus loin : décorateurs avec arguments et classes

Parfois, tu veux paramétrer ton décorateur. Par exemple, un décorateur @repeter(3) qui exécute la fonction 3 fois. Pour cela, il faut un décorateur... qui retourne un décorateur !

def repeter(nb_fois):
# Cette fonction est l'usine à décorateurs
def decorateur_usine(fonction):
# C'est le vrai décorateur
def wrapper():
for _ in range(nb_fois):
fonction()
return wrapper
return decorateur_usine

@repeter(nb_fois=3)
def dire_coucou():
print("Coucou !")

dire_coucou() # Affiche "Coucou !" trois fois.

Tu peux aussi créer des décorateurs sous forme de classes, en utilisant la méthode spéciale __call__. C'est très utile si ton décorateur a besoin de garder un état complexe.

Conclusion : Un outil indispensable

Les décorateurs, c'est comme une superpuissance pour ton code Python. Ils te permettent de respecter un principe fondamental de la programmation : la séparation des préoccupations. La fonction fait son travail principal, et les décorateurs gèrent tout ce qui est autour (logs, sécurité, performances, etc.).

Au début, ça peut faire tourner la tête, mais avec un peu de pratique, l'utilisation du @ deviendra naturelle. N'hésite pas à revenir sur les exemples de cet article, à les tester dans ton interpréteur Python et à créer tes propres décorateurs pour tes projets NSI. C'est en forgeant qu'on devient forgeron !

📚 Pour aller plus loin

Questions fréquentes

À quoi sert vraiment un décorateur en Python ?

Un décorateur sert à modifier ou à étendre le comportement d'une fonction (ou d'une classe) sans changer son code source. C'est un outil de méta-programmation qui permet d'ajouter des fonctionnalités comme la journalisation, la validation, la mise en cache ou le contrôle d'accès de manière propre et réutilisable.

Est-ce que l'ordre des décorateurs a une importance ?

Oui, absolument ! Les décorateurs s'appliquent de bas en haut, c'est-à-dire du plus proche de la définition de la fonction vers le haut. Dans <code>@deco1 @deco2 def ma_fonction():</code>, <code>deco2</code> est appliqué en premier, puis <code>deco1</code> enveloppe le résultat. Pense à des poupées russes : la première décorée est au centre.

Comment faire un décorateur qui fonctionne avec des fonctions ayant n'importe quels arguments ?

Il faut utiliser <code>*args</code> et <code>**kwargs</code> dans la fonction wrapper à l'intérieur du décorateur. Cela permet de capturer tous les arguments positionnels et nommés et de les transmettre à la fonction originale. Exemple : <code>def wrapper(*args, **kwargs): return fonction_a_decorer(*args, **kwargs)</code>.

Les décorateurs modifient-ils le nom de la fonction originale ?

Oui, un piège classique ! Après décoration, <code>ma_fonction.__name__</code> affichera le nom de la fonction wrapper (souvent 'wrapper'). Pour conserver le nom et la docstring originels, utilise le décorateur <code>@functools.wraps(fonction_a_decorer)</code> au-dessus de ta fonction wrapper. C'est une bonne pratique essentielle.

Bravo ! Tu as lu cet article
Inscris-toi pour sauvegarder ta progression et gagner des XP
Creer mon compte
decorateurs PythonPython avance
Pixel