Décorateur

Dans l'article précédent, nous avons découvert les fermetures en résolvant un problème d'exigence. Cet article fera de même, en faisant évoluer lentement une exigence et en comprenant étape par étape les décorateurs Python.

Tout d'abord, il existe une telle fonction qui génère les informations de pointage des employés :

def punch():
    print('昵称:两点水  部门:做鸭事业部 上班打卡成功')
punch()

Le résultat de sortie est le suivant :

昵称:两点水  部门:做鸭事业部 上班打卡成功

Ensuite, les commentaires sur le produit, non, pourquoi le pointage n'a-t-il pas de date précise ? Ajoutez la date spécifique du pointage, cela devrait être très simple et peut être résolu en quelques minutes. D'accord, ajoutez simplement le code pour imprimer la date, comme suit :

import time
def punch():
    print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
    print('昵称:两点水  部门:做鸭事业部 上班打卡成功')
punch()

Le résultat de sortie est le suivant :

2018-01-09
昵称:两点水  部门:做鸭事业部 上班打卡成功

C'est bien de le changer comme ça, mais cela change la structure fonctionnelle de la fonction lorsque cette fonction est. défini, il imprime Les informations et les invites d'un employé ont été saisies avec succès. Désormais, l'ajout d'un code pour imprimer la date peut entraîner de nombreux problèmes de duplication de code. Par exemple, il existe un autre endroit qui n'a besoin que d'imprimer les informations sur les employés et de les saisir avec succès, mais aucune date n'est requise. Alors, devez-vous réécrire une fonction ? De plus, cette méthode fonctionnelle d'impression de la date actuelle est fréquemment utilisée et peut être appelée comme fonction publique de chaque méthode de module. Bien entendu, tout cela est considéré comme un projet global.

Puisque c'est le cas, nous pouvons utiliser la programmation fonctionnelle pour modifier cette partie du code. Parce que grâce à des études précédentes, nous savons que les fonctions Python ont deux caractéristiques.Une fonction est aussi un objet, et les fonctions peuvent être imbriquées dans des fonctions. Ensuite, modifiez le code pour qu'il ressemble à ceci :

import time
def punch():
    print('昵称:两点水  部门:做鸭事业部 上班打卡成功')
def add_time(func):
    print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
    func()
add_time(punch)

Résultat de sortie :

2018-01-09
昵称:两点水  部门:做鸭事业部 上班打卡成功

N'est-ce pas. c'est vrai ? J'ai trouvé que de cette façon, la méthode de pointage n'est pas modifiée, et toute fonction qui doit imprimer la date actuelle peut simplement transmettre la fonction dans add_time, juste comme ceci :

import time
def punch():
    print('昵称:两点水  部门:做鸭事业部 上班打卡成功')
def add_time(func):
    print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
    func()
def holiday():
    print('天气太冷,今天放假')
add_time(punch)
add_time(holiday)

Imprimer le résultat :

2018-01-09
昵称:两点水  部门:做鸭事业部 上班打卡成功
2018-01-09
天气太冷,今天放假

Est-ce facile utiliser la programmation de fonctions ? Pratique, mais chaque fois que nous l'appelons, nous devons passer la fonction d'origine en paramètre. Existe-t-il une meilleure façon de l'implémenter ? Oui, c'est le décorateur que je vais présenter dans cet article, car la façon d'écrire un décorateur est en fait similaire à celle d'une fermeture, mais il n'y a pas de variables libres, voici donc la façon d'écrire le décorateur dans le code ci-dessus à titre de comparaison. Quelle est la différence entre l'écriture et la programmation fonctionnelle ?

import time
def decorator(func):
    def punch():
        print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
        func()
    return punch
def punch():
    print('昵称:两点水  部门:做鸭事业部 上班打卡成功')
f = decorator(punch)
f()

Résultats de sortie :

2018-01-09
昵称:两点水  部门:做鸭事业部 上班打卡成功

Grâce au code, vous pouvez savoir que la fonction décorateur fait généralement ces trois choses :

Reçoit une fonction en tant que paramètre

Imbrique une fonction wrapper, et la fonction wrapper recevra les mêmes paramètres de la fonction d'origine, Et exécuter la fonction d'origine, et également exécuter des fonctions supplémentaires

Renvoyer les fonctions imbriquées

Cependant, si vous regardez attentivement ce code, pourquoi la façon d'écrire ce décorateur est-elle plus gênante que la programmation fonctionnelle ? Et cela semble compliqué, voire un peu inutile.

C'est parce que nous n'avons pas encore utilisé le « sucre de syntaxe » du décorateur. En regardant le code ci-dessus, nous pouvons voir que lorsque Python a introduit le décorateur (Decorator), il n'a introduit aucune nouvelle fonctionnalité de syntaxe. sur la caractéristique de la syntaxe de la fonction. Cela montre également que les décorateurs ne sont pas propres à Python, mais une idée de programmation commune à tous les langages. C'est juste que Python a conçu le sucre de syntaxe @, qui rend le processus de définition d'un décorateur, appelant le décorateur la fonction d'origine et attribuant le résultat au nom d'objet de la fonction d'origine plus simple, plus pratique et plus facile à utiliser, de sorte que le noyau du décorateur Python peut dire que c'est son sucre syntaxique.

Alors comment utiliser son sucre de syntaxe ? C'est très simple. Après avoir écrit la fonction décorateur selon la méthode d'écriture ci-dessus, ajoutez directement @ et le nom de la fonction du décorateur à la fonction d'origine. Comme suit :

import time
def decorator(func):
    def punch():
        print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
        func()
    return punch
@decorator
def punch():
    print('昵称:两点水  部门:做鸭事业部 上班打卡成功')
punch()

Résultat de sortie :

2018-01-09
昵称:两点水  部门:做鸭事业部 上班打卡成功

Ensuite, c'est très pratique pour nos appels. Par exemple, dans l'exemple, après avoir utilisé le décorateur, nous pouvons directement ajouter le sucre de syntaxe du décorateur à la fonction d'origine. il n'y a aucune modification à cette fonction et le lieu d'appel n'a pas besoin d'être modifié.

Cependant, il y a toujours eu un problème ici, c'est-à-dire que la sortie des informations punch-in est corrigée, nous devons donc les transmettre via des paramètres. Comment écrire le décorateur ? La fonction dans le décorateur peut utiliser des paramètres variables *args, mais uniquement l'utilisation de *args ne peut pas inclure entièrement tous les paramètres. Par exemple, les paramètres de mots-clés ne peuvent pas être utilisés. Afin d'être compatible avec les paramètres de mots-clés, nous devons également ajouter **kwargs .

Par conséquent, la forme finale du décorateur peut s'écrire comme ceci :

import time
def decorator(func):
    def punch(*args, **kwargs):
        print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
        func(*args, **kwargs)
    return punch
@decorator
def punch(name, department):
    print('昵称:{0}  部门:{1} 上班打卡成功'.format(name, department))
@decorator
def print_args(reason, **kwargs):
    print(reason)
    print(kwargs)
punch('两点水', '做鸭事业部')
print_args('两点水', sex='男', age=99)

Le résultat de sortie est le suivant :

2018-01-09
昵称:两点水  部门:做鸭事业部 上班打卡成功
2018-01-09
两点水
{'sex': '男', 'age': 99}

C'est la fin de la série d'articles sur la prise en main de Python.


Formation continue
  • Recommandations de cours
  • Téléchargement du didacticiel