Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐍
Avance 25 min Python

Les decorateurs Python

Pourquoi les décorateurs Python ?

Les décorateurs en Python sont une fonctionnalité puissante et polyvalente qui permet d'ajouter des comportements supplémentaires à des fonctions, des méthodes ou des classes. Ils sont largement utilisés dans la communauté Python pour augmenter la flexibilité et la productivité du code.

  • Contexte réel : Les développeurs Python les utilisent fréquemment dans divers cas tels que le logging, le timing des fonctions, l'authentification, l'introspection, et bien plus encore. Ils permettent d'ajouter des fonctionnalités sans modifier le code original de la fonction.
  • Un cas d'utilisation concret : Imaginez une application web où vous voulez mesurer le temps d'exécution de chaque requête pour optimiser les performances. Les décorateurs vous permettent de mesurer ce temps simplement et efficacement, sans avoir à modifier chaque fonction individuellement.

Prerequis

  • Connaissances en Python avancées
    • Fonctions et méthodes
    • Arguments et paramètres
    • Exceptions
  • Outils à installer :
    • Python (v3.6 ou plus récent)
    • IDE ou éditeur de code préféré (VSCode, PyCharm, etc.)

Concepts fondamentaux

Décorateur de base

Un décorateur est une fonction qui prend une autre fonction en argument et renvoie une nouvelle fonction avec des comportements supplémentaires.

def ma_fonction():
    print("Hello, World!")
## 
def mon_decorateur(fonction):
    def wrapper():
        print("Avant l'appel")
        fonction()
        print("Après l'appel")
    return wrapper

ma_fonction = mon_decorateur(ma_fonction)

ma_fonction()

Utiliser un décorateur avec la syntaxe simplifiée

Python offre une syntaxe plus concise pour appliquer des décorateurs :

def ma_fonction():
    print("Hello, World!")
## 
@mon_decorateur
def ma_fonction():
    print("Hello, World!")

ma_fonction()

Décorateur avec arguments

Les décorateurs peuvent également accepter des arguments. Pour cela, on utilise une fonction interne qui prend un nombre indéfini d'arguments.

def mon_decorateur(avec_argument):
    def decorateur(fonction):
        def wrapper(*args, **kwargs):
            print(f"Avant l'appel avec argument : {avec_argument}")
            fonction(*args, **kwargs)
            print("Après l'appel")
        return wrapper
    return decorateur

@mon_decorateur(42)
def ma_fonction():
    print("Hello, World!")

ma_fonction()

Multiple décorateurs

On peut appliquer plusieurs décorateurs à une fonction en les chaînant :

def decorateur1(fonction):
    def wrapper():
        print("Decorator 1 avant")
        fonction()
        print("Decorator 1 après")
    return wrapper

def decorateur2(fonction):
    def wrapper():
        print("Decorator 2 avant")
        fonction()
        print("Decorator 2 après")
    return wrapper

@decorateur1
@decorateur2
def ma_fonction():
    print("Hello, World!")

ma_fonction()

Mise en pratique : projet fil rouge

Dans ce projet fil rouge, nous allons créer un simple gestionnaire de tâches avec des fonctionnalités comme l'ajout, la suppression et la affichage des tâches. Nous utiliserons les décorateurs pour ajouter des comportements supplémentaires, comme le logging.

Étape 1 : Structure du projet

Créez un nouveau dossier gestionnaire_taches et insérez-y les fichiers suivants :

gestionnaire_taches/
├── main.py
├── tache.py
└── utils.py

Étape 2 : Définition des classes

Dans tache.py, définissons la classe Tache pour représenter une tâche.


class Tache:
    def __init__(self, description):
        self.description = description
        self.terminee = False

    def terminer(self):
        self.terminee = True

Étape 3 : Définition des décorateurs

Dans utils.py, définissons les décorateurs que nous utiliserons.


import logging

logging.basicConfig(level=logging.INFO)

def log_execution(fonction):
    def wrapper(*args, **kwargs):
        logging.info(f"Appel à {fonction.__name__} avec arguments {args} et keyword arguments {kwargs}")
        result = fonction(*args, **kwargs)
        logging.info(f"{fonction.__name__} a retourné {result}")
        return result
    return wrapper

def verif_acces(fonction):
    def wrapper(*args, **kwargs):
        if not hasattr(args[0], 'est_admin'):
            raise Exception("Accès refusé")
        return fonction(*args, **kwargs)
    return wrapper

Étape 4 : Implémentation des fonctionnalités

Dans main.py, implémentons les fonctionnalités du gestionnaire de tâches.


from tache import Tache
import logging

logging.basicConfig(level=logging.INFO)

class GestionnaireTaches:
    def __init__(self):
        self.taches = []

    @log_execution
    def ajouter_tache(self, description):
        nouvelle_tache = Tache(description)
        self.taches.append(nouvelle_tache)
        return nouvelle_tache

    @log_execution
    @verif_acces
    def supprimer_tache(self, index):
        if 0 <= index < len(self.taches):
            del self.taches[index]
            logging.info("Tâche supprimée avec succès")
        else:
            raise IndexError("Index de tâche invalide")

    @log_execution
    def afficher_taches(self):
        for i, tache in enumerate(self.taches):
            print(f"{i}: {tache.description} (Terminée: {'Oui' if tache.terminee else 'Non'})")

Étape 5 : Utilisation du gestionnaire de tâches

Ajoutez le code suivant à main.py pour tester les fonctionnalités.


if __name__ == "__main__":
    g = GestionnaireTaches()

    try:
        tache1 = g.ajouter_tache("Faire les courses")
        tache2 = g.ajouter_tache("Nettoyer la maison")

        g.afficher_taches()

        g.supprimer_tache(0)

        g.afficher_taches()
    except Exception as e:
        print(e)

Étape 6 : Exécution du code

Exécutez le script main.py en utilisant la commande suivante :

python main.py

Vous devriez voir des messages de logging indiquant l'exécution et les résultats des opérations.

Erreurs fréquentes et debugging

1. Erreur : Fonctionnalité manquante

Code incorrect :

def ma_fonction():
    print("Hello, World!")

Code correct :

@mon_decorateur
def ma_fonction():
    print("Hello, World!")

2. Erreur : Decorator not callable

Code incorrect :

@mon_decorateur(42)
def ma_fonction():
    pass

Code correct :

def mon_decorateur(avec_argument):
    def decorateur(fonction):
        def wrapper(*args, **kwargs):
            print(f"Avant l'appel avec argument : {avec_argument}")
            fonction(*args, **kwargs)
            print("Après l'appel")
        return wrapper
    return decorateur

@mon_decorateur(42)
def ma_fonction():
    pass

3. Erreur : Multiple decorators not working

Code incorrect :

@decorateur1
@decorateur2
def ma_fonction():
    print("Hello, World!")

Code correct :

Vérifiez que les décorateurs sont bien définis et qu'ils ne présentent pas d'erreurs syntaxiques.

Pour aller plus loin

  • Méta-programmation avancée avec inspect : Explorez comment utiliser le module inspect pour obtenir des informations sur les fonctions.
  • Decorators for classes and methods : Apprenez à créer et utiliser des décorateurs pour les méthodes et les classes.
  • Asynchronous decorators : Découvrez comment créer des décorateurs asynchrones pour gérer des opérations non bloquantes.

Défi pratique

Créez un simple API de blog avec des fonctionnalités comme la création, la lecture et la suppression d'articles. Utilisez les décorateurs pour ajouter des comportements supplémentaires comme le logging et l'autorisation.

Besoin d'aide sur Python ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce qu'un décorateur en Python ?
Un décorateur en Python est une fonction qui prend une autre fonction ou une méthode comme argument et ajoute des fonctionnalités supplémentaires à cette fonction ou méthode sans modifier son code original.
Comment créer un décorateur simple en Python ?
Pour créer un décorateur, vous définissez une fonction qui prend une autre fonction comme paramètre et retourne une nouvelle fonction qui ajoute les fonctionnalités souhaitées.
Où est le meilleur endroit pour apprendre à utiliser les décorateurs en Python ?
Il existe de nombreux cours en ligne gratuits sur des plateformes comme Coursera, Udemy et edX qui offrent des formations détaillées sur l'utilisation des décorateurs en Python. Vous pouvez également consulter la documentation officielle de Python pour des informations plus approfondies.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.