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 !