Les décorateurs sont une partie importante de Python. En termes simples : ce sont des fonctions qui modifient les fonctionnalités d'autres fonctions. Ils aident à rendre notre code plus court et plus Pythonique. La plupart des débutants ne savent pas où les utiliser, alors je vais partager quelques domaines où les décorateurs peuvent rendre votre code plus propre. D'abord, discutons de la façon d'écrire vos propres décorateurs.
C'est probablement l'un des concepts les plus difficiles à maîtriser. Nous allons en discuter une étape à la fois afin que vous puissiez bien le comprendre.
Tout est un objet
D'abord, comprenons les fonctions en Python :
Définir des fonctions à l'intérieur de fonctions
C'étaient les bases des fonctions. Poussons vos connaissances un peu plus loin. En Python, nous pouvons définir une fonction à l'intérieur d'une autre fonction :
Maintenant, nous savons que nous pouvons définir d'autres fonctions à l'intérieur d'une fonction. C'est-à-dire : nous pouvons créer des fonctions imbriquées. Maintenant, vous devez apprendre un peu plus : les fonctions peuvent aussi renvoyer des fonctions.
Retourner des fonctions à partir de fonctions
En fait, il n'est pas nécessaire d'exécuter une autre fonction à l'intérieur d'une fonction ; nous pouvons aussi la retourner comme sortie :
Regardez à nouveau ce code. Dans l'instruction if/else, nous retournons greet et welcome, pas greet() et welcome(). Pourquoi cela ? C'est parce que lorsque vous mettez une paire de parenthèses après, la fonction est exécutée ; cependant, si vous ne mettez pas de parenthèses après, elle peut être transmise et assignée à d'autres variables sans être exécutée. Comprenez-vous ? Laissez-moi expliquer un peu plus en détail.
Quand nous écrivonsa = hi(),hi()elle est exécutée, et comme le paramètre name a pour valeur par défaut yasoob, la fonctiongreet()est retournée.
-
Nous pouvons aussi afficherhi()(), ce qui donnera en sortie :vous êtes maintenant dans la fonction greet()。
-
Si nous changeons l'instruction ena = hi(name = "ali"), alorswelcome()la fonction sera retournée.
Passer une fonction comme argument à une autre fonction
Vous avez maintenant toutes les connaissances nécessaires pour apprendre ce que sont réellement les décorateurs. Les décorateurs vous permettent d'exécuter du code avant et après une fonction.
Votre premier décorateur
Dans l'exemple précédent, nous avons en fait déjà créé un décorateur ! Maintenant, modifions le décorateur précédent et écrivons un programme légèrement plus utile :
Vous voyez ? Nous venons juste d'appliquer les principes que nous avons appris plus tôt. C'est exactement ce que font les décorateurs en Python ! Ils enveloppent une fonction et modifient son comportement d'une manière ou d'une autre. Maintenant, vous vous demandez peut-être : dans notre code, nous n'avons pas utilisé le@symbole ? Ce n'est qu'un raccourci pour générer une fonction décorée. Voici comment nous utilisons@pour exécuter le code précédent :
J'espère que vous avez maintenant une compréhension de base du fonctionnement des décorateurs Python. Il y a un problème si nous exécutons le code suivant :
print(a_function_requiring_decoration.__name__) # Output: wrapTheFunction
Ce n'est pas ce que nous voulions ! La sortie devrait être "a_function_requiring_decoration". Ici, la fonction a été remplacée par warpTheFunction. Cela a écrasé le nom et la docstring de notre fonction. Heureusement, Python nous fournit une fonction simple pour résoudre ce problème, à savoir functools.wraps. Modifions l'exemple précédent pour utiliser functools.wraps :
C'est beaucoup mieux maintenant. Ensuite, apprenons quelques cas d'utilisation courants des décorateurs.
Spécification du modèle :
Remarque :@wrapsIl accepte une fonction à décorer et ajoute la fonctionnalité de copier le nom de la fonction, la docstring, la liste des arguments, etc. Cela nous permet d'accéder aux attributs de la fonction avant décoration à l'intérieur du décorateur.
Cas d'utilisation
Voyons maintenant où les décorateurs brillent vraiment, et comment leur utilisation facilite la gestion de certaines choses.
Authorization
Les décorateurs peuvent aider à vérifier si quelqu'un est autorisé à utiliser un endpoint d'une application web. Ils sont très utilisés dans les frameworks web Flask et Django. Voici un exemple d'utilisation de l'autorisation basée sur des décorateurs :
Journalisation
La journalisation est un autre point fort de l'utilisation des décorateurs. Voici un exemple :
Je suis sûr que vous pensez déjà à une autre utilisation astucieuse des décorateurs.
Décorateurs avec paramètres
Réfléchissez à ceci : @wraps n'est-il pas aussi un décorateur ? Mais il prend un paramètre, tout comme n'importe quelle fonction ordinaire peut le faire. Alors pourquoi ne faisons-nous pas cela aussi ? C'est parce que lorsque vous utilisez la syntaxe @my_decorator, vous appliquez une fonction d'encapsulation qui prend une seule fonction comme argument. Rappelez-vous, tout en Python est un objet, et cela inclut les fonctions ! Avec cela à l'esprit, nous pouvons écrire une fonction qui renvoie une fonction d'encapsulation.
Intégrer des décorateurs dans des fonctions
Revenons à l'exemple de journalisation et créons une fonction d'encapsulation qui nous permet de spécifier un fichier journal pour la sortie.
Classes de décorateurs
Maintenant, nous avons un décorateur logit adapté à la production, mais lorsque certaines parties de notre application sont encore fragiles, les exceptions peuvent nécessiter une attention plus urgente. Par exemple, parfois vous voulez simplement enregistrer dans un fichier. D'autres fois, vous voulez envoyer un problème qui attire votre attention par e-mail tout en conservant un journal pour archivage. C'est un scénario d'utilisation de l'héritage, mais jusqu'à présent nous n'avons vu que des fonctions utilisées pour construire des décorateurs.
Heureusement, les classes peuvent aussi être utilisées pour construire des décorateurs. Alors maintenant, reconstruisons logit en utilisant une classe plutôt qu'une fonction.
Cette implémentation présente l'avantage supplémentaire d'être plus propre que l'approche par fonction imbriquée, et l'encapsulation d'une fonction utilise toujours la même syntaxe qu'auparavant :
@logit()
def myfunc1():
pass
Maintenant, créons une sous-classe de logit pour ajouter une fonctionnalité d'e-mail (bien que le sujet de l'e-mail ne soit pas développé ici).
Désormais, @email_logit aura le même effet que @logit, mais en plus de la journalisation, il enverra également un e-mail à l'administrateur.
Adresse de l'article original : https://eastlakeside.gitbooks.io/interpy-zh/content/decorators/