Maison >développement back-end >Tutoriel Python >Détails du décorateur Python

Détails du décorateur Python

尚
avant
2020-06-18 17:40:061882parcourir

Un décorateur est essentiellement une fonction Python, qui permet à d'autres fonctions d'ajouter des fonctions supplémentaires sans apporter de modifications au code. La valeur de retour du décorateur est également un objet fonction .

<.>Détails du décorateur Python

est souvent utilisé dans des scénarios avec des exigences transversales, telles que : l'insertion de journaux, les tests de performances, le traitement des transactions, la mise en cache, la vérification des autorisations, etc. Les décorateurs sont une excellente conception pour résoudre ce genre de problème. Avec les décorateurs, nous pouvons extraire une grande quantité de code similaire qui n'a rien à voir avec la fonction elle-même et continuer à le réutiliser.

Regardons d'abord un exemple simple :

def now():
    print('2017_7_29')
Maintenant, il y a une nouvelle exigence, j'espère enregistrer le journal d'exécution de la fonction, j'ajoute donc le code du journal dans le code :

def now():
    print('2017_7_29')
    logging.warn("running")

假设有类似的多个需求,怎么做?再写一个logging在now函数里?这样就造成大量雷同的代码,为了减少重复写代码,我们可以这样做,重新定义一个函数:专门处理日志 ,日志处理完之后再执行真正的业务代码.

def use_logging(func):     
    logging.warn("%s is running" % func.__name__)     
    func()  
def now():     
    print('2017_7_29')    
use_logging(now)
En implémentation,

ce n'est pas difficile logiquement, mais dans ce cas, il faut à chaque fois passer une fonction en paramètre à la fonction log. De plus, cette méthode a détruit la structure logique du code d'origine lors de l'exécution de la logique métier auparavant, now() était exécutée, mais elle doit maintenant être remplacée par use_logging(now).

Alors, y a-t-il une meilleure façon ? Bien sûr, la réponse est celle des décorateurs.

Tout d'abord, vous devez comprendre qu'une fonction est également un objet et que les objets de fonction peuvent être affectés à des variables, de sorte que la fonction peut également être appelée via des variables. Par exemple :

(=

Décorateur simple

Essentiellement, le décorateur est une fonction d'ordre supérieur qui renvoie une fonction. Par conséquent, nous devons définir un décorateur capable d'imprimer des journaux, qui peut être défini comme suit :

def log(func):
    def wrapper(*args,**kw):
        print('call %s():'%func.__name__)
        return func(*args,**kw)
    return wrapper
# 由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,
# 只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。
# wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。
# 在wrapper()函数内,首先打印日志,再紧接着调用原始函数。
Ce qui précède

, car c'est un décorateur, accepte une fonction comme paramètre et renvoie une fonction. Maintenant, exécutez : log

now = log(now)
now()
rrreeFonction

log est un décorateur. Il enveloppe la fonction qui exécute la vraie méthode métier dans la fonction. Dans cet exemple, lorsque la fonction entre, elle est appelée un aspect (Aspect), et cette méthode de programmation est appelée programmation orientée aspect (Aspect-Oriented Programming).

Utiliser le sucre syntaxique :

输出结果:
call now():
2017_7_28
Le symbole @ est du sucre syntaxique pour les décorateurs. Il est utilisé lors de la définition de fonctions pour éviter une autre opération d'affectation

De cette façon, nous vous. peut omettre la phrase now =

log(now) et appeler now() directement pour obtenir le résultat souhaité. Si nous avons d'autres fonctions similaires, nous pouvons continuer à appeler le décorateur pour décorer la fonction sans modifier la fonction à plusieurs reprises ni ajouter de nouveaux packages. De cette façon, nous améliorons la réutilisabilité du programme et augmentons la lisibilité du programme.

La raison pour laquelle les décorateurs sont si pratiques à utiliser en Python est que les fonctions Python peuvent être transmises en tant que paramètres à d'autres fonctions comme les objets ordinaires, peuvent être affectées à d'autres variables et peuvent être utilisées comme valeurs de retour. . Peut être défini dans une autre fonction.

Décorateur avec paramètres :

Si le décorateur lui-même doit transmettre des paramètres, vous devez écrire une fonction de haut niveau qui renvoie le décorateur. Les fonctions Order sont un peu plus compliquées à écrire. Par exemple, pour personnaliser le texte du log :

@logdef now():
    print('2017_7_28')
Ce décorateur imbriqué à 3 couches s'utilise de la manière suivante :

def log(text):
    def decorator(func):
            def wrapper(*args,**kw):
                        print('%s %s()'%(text,func.__name__))
                        return func(*args,**kw)        
            return wrapper    
     return decorator
est équivalent à

@log(()
now()
car nous l'avons dit que les fonctions sont aussi des objets, elles ont des attributs tels que

, mais si vous regardez les fonctions décorées par le décorateur, leur __name__ est passé de l'original __name__ à 'now' : 'wrapper'

<span style="color: #000000;">now = log('goal')(now)<br># 首先执行log('execute'),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数<br>now()</span>
à cause de celui renvoyé Le nom de la fonction

est wrapper(), vous devez donc copier le 'wrapper' et les autres attributs de la fonction d'origine dans la fonction __name__ Sinon, du code qui s'appuie sur la fonction. la signature ne s'exécutera pas correctement. wrapper()

Il n'est pas nécessaire d'écrire du code comme

Le wrapper.__name__ = func.__name__ intégré à Python fait cela. Par conséquent, un décorateur complet s'écrit comme suit : functools.wraps

print(now.__name__)# wrapper
rrree

décoration de classe. Appareil  :

Regardons les décorateurs de classe Par rapport aux décorateurs de fonctions, les décorateurs de classe présentent les avantages d'une plus grande flexibilité, d'une cohésion élevée et d'une encapsulation. L'utilisation de décorateurs de classe peut également s'appuyer sur la méthode __call__ à l'intérieur de la classe. Lorsque le formulaire @ est utilisé pour attacher le décorateur à une fonction, cette méthode sera appelée

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
Résumé :

Généralisé dans. en d’autres termes, le but d’un décorateur est d’ajouter des fonctionnalités supplémentaires à un objet existant. ​

En même temps, dans le modèle de conception orienté objet (POO), le décorateur est appelé le modèle de décoration. Le mode de décoration de la POO doit être implémenté par héritage et combinaison, et Python, en plus de prendre en charge le décorateur de la POO, prend également en charge les décorateurs directement à partir du niveau syntaxique. Le décorateur de Python peut être implémenté sous forme de fonction ou de classe.

Pour plus de connaissances connexes, veuillez prêter attention à la colonne tutoriel vidéo Python

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer