Python - Introduction aux décorateurs (decorator)

Christophe Thibault
08 novembre 2023

En tant que Data Scientist (et développeur python), j'ai besoin d'utiliser et de réutiliser les mêmes fonctions en Python, mais il peut parfois être utile d'ajouter quelques différences ou comportements mineurs à ces fonctions. Au lieu d'utiliser des fonctions internes, les décorateurs pourraient être le moyen le plus simple d'y parvenir.

NB : cet article “Python decorator. An introduction” est disponible en anglais via le profil linkedin de son auteur Christophe Thibault.

NB : Cet article fait partie d’une série d'articles dont le premier épisode Astuce Python : la fonction PIPE est d’ores et déjà disponible. 

En tant que Data Scientist (et développeur python), j'ai besoin d'utiliser et de réutiliser les mêmes fonctions en Python, mais il peut parfois être utile d'ajouter quelques différences ou comportements mineurs à ces fonctions. 

Au lieu d'utiliser des fonctions internes, les décorateurs pourraient être le moyen le plus simple d'y parvenir. 

Qu’est ce que des décorateurs Python (decorator) ?

Les décorateurs offrent un moyen élégant d’étendre ou de modifier le comportement des fonctions en Python. Ils me permettent d'envelopper ou de modifier des fonctions sans altérer leur code principal. Cela s'avère particulièrement utile pour des tâches telles que la journalisation, la synchronisation, l'authentification et la gestion d'autres problèmes transversaux de manière propre et réutilisable. 

Comment créer des décorateurs Python (decorator) ?

Prenons un exemple simple - une fonction qui imprime une seule phrase :

 <script> 
def cat_func():
    print('Ozzy is a cat')

cat_func()
>>'Ozzy is a cat'
<script> 

Si vous souhaitez changer le comportement de cette fonction, les décorateurs Python peuvent être utilisés comme cela :

 <script> 
def my_decorator(func):
    def wrapper():
        result = func().replace('cat', 'Bengal ' + 'cat')
        return result
    return wrapper
    <script> 
 <script>
@my_decorator
def cat_func():
    return 'Ozzy is a cat'

cat_func()
>> 'Ozzy is a Bengal cat'
<script> 

Désormais, la fonction cat_func renvoie non seulement Ozzy est un chat, mais Ozzy est un chat du Bengale. 

Le mot Bengal est inséré avant le mot chat : les décorateurs enveloppent une fonction, modifiant son comportement. 

Python permet d'utiliser les décorateurs de manière plus simple avec le symbole @. C'est un moyen plus simple d'utiliser cat_func = my_decorator(cat_func).

Si vous devez utiliser un argument (c'est à dire un nom dans l'exemple ci-dessous), vous devez utiliser *args et/ou **kwargs dans la fonction wrapper : wrapper(*args, **kwargs)

 <script>

def my_decorator(func):
    def wrapper(*args):
        result = func(*args).replace('cat', 'Bengal ' + 'cat')
        return result
    return wrapper

@my_decorator
def cat_func2(name):
  return f'{name} is a cat'

cat_func2('Pépin')
>> Pépin is a Bengal cat
<script> 

Comment supprimer le décorateur (decorator) ?

Une fois que vous avez appliqué un décorateur à une fonction, vous ne pouvez pas revenir et obtenir le comportement initial de cette fonction. 

Revenir facilement et supprimer le décorateur - encapsuler la fonction de functools - est le moyen de désencapsuler la fonction.

 <script>

from functools import wraps

def my_decorator(func):
  @wraps(func)
  def wrapper(*args):
    return func(*args).replace('cat', 'Bengal ' + 'cat')
  return wrapper

cat_func2('Cosy')
>> Cosy is a Bengal cat

cat_func2 = cat_func2.__wrapped__
cat_func2('Cozy')
>> Cozy is a cat
 <script> 

Comme vous pouvez le voir sur l'exemple ci-dessus, la fonction peut être défaite avec l'attribut .__wrapped__. Facile ! 

Vous êtes désormais capable de comprendre le concept de décorateur en python, et d'utiliser des cas simples. Voici quelques liens pour obtenir plus d'informations sur ce sujet et le lien vers la bibliothèque functools (functools). 

 #python #coding #decorator #functools

Christophe Thibault

D'abord physicien, j'ai basculé dans une vie plus récente en tant que datascientist diplômé de TeleCom ParisTech. La data et le machine learning sont devenus mon quotidien, mais entre deux sessions de debugging, je m'évade sur les notes de ma guitare. Mes journées oscillent entre déchiffrage de scripts et sorties sur des sentiers de nature. Un passionné de data qui jongle entre les algorithmes, les accords de guitare et les trails en pleine nature !