Python – Améliorez votre code avec les décorateurs

-

Dans cet article, nous allons voir à quel point les décorateurs sont puissants. Si vous êtes nouveau à Python (et peut-être même si vous ne l’êtes pas), vous n’avez probablement jamais entendu parler de cette construction. C’est quelque chose de spécifique à Python, qui permet de définir un comportement général commun à de nombreuses méthodes dans une fonction séparée. Moi-même, j’ai découvert cela que tout récemment !

Par exemple, supposons que nous ayons les méthodes suivantes :

def sum(a, b):
  return a+b
def subtract(a, b):
  return a-b

Nous voulons maintenant imprimer le résultat dans la console, avant de le renvoyer. Que devons-nous faire ? La première idée est d’ajouter une instruction print dans toutes les fonctions. Mais que se passe-t-il si nous décidons de sauvegarder le résultat dans un fichier ? Nous devrions à nouveau modifier toutes les fonctions.

Au lieu de cela, nous pouvons créer un décorateur log_result et l’ajouter aux méthodes :

@log_result
def sum(a, b):
  return a+b
@log_result
def subtract(a, b):
  return a-b

Et maintenant, si nous voulons changer l’endroit où nous écrivons la sortie, nous devons juste changer le code dans log_result .

Qu’est-ce qu’un décorateur (decorator) ?

Nous avons vu comment les décorateurs peuvent être utilisés, mais qu’est-ce qu’un décorateur exactement ?
Pour vous donner une définition formelle,

A decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.

En traduction libre :

Un décorateur est une fonction qui prend une autre fonction et étend le comportement de cette dernière sans la modifier explicitement.
Décortiquons cela morceau par morceau.

Tout d’abord, un décorateur est une fonction qui prend une autre fonction comme paramètre : cela signifie que nous définirons le décorateur log_result comme :

def log_result(func):

Ensuite, nous devons modifier cette fonction et retourner la version modifiée.
Nous pouvons donc créer une fonction interne (que j’ai appelée inner pour simplifier) qui exécute func , imprime le résultat et renvoie enfin cette valeur :

def log_result(func):
  def inner():
    res = func()
    print(res)
    return res

Enfin, le décorateur doit retourner la fonction modifiée :

def log_result(func):
  def inner():
    res = func()
    print("The result is ", res)
    return res
  
  return inner

Nous avons créé notre premier décorateur ! Enfin, pas vraiment. Il ne fonctionne que si la fonction à laquelle nous l’ajoutons n’a pas de paramètres. Par exemple :

@log_result
def get_even_digits():
  return [0, 2, 4, 6, 8]

Lorsque nous appelons cette fonction, le journal s’imprime à l’écran :

>>> l = get_even_digits()
The result is [0, 2, 4, 6, 8]

Cependant, si nous essayons de l’utiliser avec les méthodes sum et subtract de la version précédente, le code ne s’exécutera pas correctement.

Le problème est que nous n’avons pas donné à la fonction modifiée la possibilité de recevoir les paramètres qui devraient être passés à func . Heureusement, ce problème peut être résolu facilement. Nous allons redéfinir inner comme suit :

def log_result(func):
  def inner(**kwargs):
    res = func(kwargs)
    print("The result is ", res)
    return res
  
  return inner

Maintenant, inner peut obtenir n’importe quel nombre de paramètres, et les passer directement à la fonction. Nous l’avons fait !

>>>s = sum(3, 5)
The result is 8
>>>d = subtract(8,5)
The result is 3

Décorateurs avec paramètres

Enfin, nous pouvons vouloir passer des paramètres supplémentaires au décorateur. Par exemple, nous pouvons vouloir imprimer également un nom avec le résultat, afin de savoir de quelle opération provient ce journal.

Pour ce faire, nous devons modifier légèrement la fonction :

def log_with_name(name):
  def log_result(f):
    def inner(x):
      res = f(x)
      print(name + ": " + str(res))
      return inner
  return log_result

Voyons ce qui se passe. La fonction log_with_name prend la chaîne du nom et renvoie le décorateur qui sera ensuite appliqué à une fonction.
Il peut être utilisé exactement comme avant :

@log_with_name("Sum")
def sum(a, b):
  return a+b
@log_with_name("Difference")
def subtract(a, b):
  return a-b

Et le résultat sera :

>>> s = sum(3, 5)
Sum: 8
>>> d = subtract(8, 3)
Difference: 5

Conclusion

Merci d’avoir lu jusqu’au bout ! Voici d’autres ressources sur les décorateurs :

Alfredhttps://www.alfreddagenais.com
Je suis un développeur Web Full Stack sénior. Chaque jour est pour moi une journée de plus pour découvrir de nouvelles idées. Le développement web et l'informatique sont omniprésents dans mon quotidien. Pour que la créativité soit à son maximum, il ne faut pas avoir peur d’expérimenter et nous avons tous que le Web est infiniment grand pour expérimenter nos idées.

Buy me a coffee Paypal Patreon Ko-Fi

Share this article

Recent posts

Popular categories

LAISSER UN COMMENTAIRE

S'il vous plaît entrez votre commentaire!
S'il vous plaît entrez votre nom ici

Recent comments