[PYTHON] Comment utiliser le décorateur

Je comprends comment écrire un décorateur.

Comme son nom l'indique, un décorateur est un décorateur. Ce que vous décorez est une fonction, une fonction. Une autre méthode.

Je comprends. C'est dur. Je comprends le décorateur.

Takeshi marmonna et se mit à courir comme s'il avait été renversé. Mais le signal a commencé à clignoter et s'est arrêté. Oui, il suit les règles de la circulation.

Et pensez à laisser le temps.

L'humanité est ce que je veux utiliser quand je peux écrire. Cependant, quand je veux vraiment l'utiliser, je ne sais pas où l'utiliser. Je ne peux pas penser à une utilisation efficace.

Une telle personne.

Oui! Je ne sais même pas!

Non, mais j'en suis peut-être venu à comprendre un peu.

Pourquoi utiliser des décorateurs

Pourquoi utiliser un décorateur?

-Utilisez des décorateurs pour éliminer les redondances indésirables et DRY

--Utilisez des décorateurs pour améliorer la lisibilité

Je peux penser à quelque chose comme ça. Ceci est souvent mentionné comme un avantage de son utilisation.

Ce n'est rien de mal! Absolument correct! Oh, je suis sûr que c'est correct!

Mais c'est juste que je ne sais pas où l'utiliser.

Parce que, pour les raisons mentionnées ci-dessus, il existe de nombreuses autres façons de le faire, non? Par exemple, y a-t-il héritage? Est-il acceptable d'en faire une fonction telle qu'elle est? Vous y êtes habitué, non? Je ne veux pas prendre la peine d'écrire quelque chose comme un décorateur. Je pense que oui, mais vous plaignez-vous?

Penses-tu? Tu ne penses pas Je pense.

Alors pourquoi oser faire appel à un décorateur?

Pour y réfléchir, il faut faire attention à la ** signification ** du traitement du code. L'essentiel ici est que nous utilisons des décorateurs pour ** la séparation de la logique métier **.

Séparation de la logique métier

Décorateur qui trace les appels de fonction

Vous avez probablement vu un exemple comme celui-ci comme première étape de la décoration.

from functools import wraps

def trace_func_call(func):
    @wraps(func)
    def wrapper(*arg):
        print(func.__name__ + ' is called.')
        return func(*arg)
    return wrapper

@trace_func_call
def spam(s):
    print((s + '!') * 5)

@trace_func_call
def ham(s):
    print((s + '?') * 5)

spam('egg')
ham('sausage')

** Résultat d'exécution **

spam is called.
egg!egg!egg!egg!egg!
ham is called.
sausage?sausage?sausage?sausage?sausage?

Un décorateur qui l'affiche chaque fois qu'une fonction est appelée.

A cette époque, le rôle joué par le décorateur n'est pas une logique métier, n'est-ce pas? L'exemple est super approprié, mais le traitement que vous voulez faire en tant que logique métier est le traitement des fonctions «spam» et «ham», n'est-ce pas? C'est un gars merdique qui répète 5 fois avec ! Ou ? Comme argument.

A ce moment-là, l'affichage de l'appel de fonction n'est pas la logique métier, mais la logique à implémenter car elle est nécessaire à la gestion. Leur logique est sémantiquement différente.

Vous pouvez utiliser des décorateurs pour séparer la logique de gestion de la logique métier. En d'autres termes, en fonction de ce que vous voulez faire, les décorateurs sont ceux qui réalisent l'intention de séparer la logique métier, qui est l'objectif principal du code, de la logique de gestion de manière soignée. Bien sûr, je ne veux pas dire que c'est le seul rôle du décorateur, mais cela donne une bonne idée de la façon d'utiliser le décorateur.

Décorateur de caisse

Ensuite, c'est un peu plus pratique. Voici un exemple de décorateur tiré de la conférence de Raymond Hettinger ** «Transformer le code en un magnifique python idiomatique» ** à PyCon US 2013.

Commençons par le code original "moins souhaitable".

def web_lookup(url, saved={}):
    if url in saved:
        return saved[url]
    page = urllib.urlopen(url).read()
    saved[url] = page
    return page

Cliquez ici pour une meilleure version du code ci-dessus en utilisant un décorateur.

def cache(func):
    saved = {}
    @wraps(func)
    def newfunc(*args):
        if args in saved:
            return saved[args]
        result = func(*args)
        saved[args] = result
        return result
    return newfunc

@cache
def web_lookup(url):
    return urllib.urlopen(url).read()

La fonction web_lookup est une fonction pour obtenir la page Web de l'URL spécifiée. A ce moment, il a une fonction pour mettre en cache les pages acquises.

C'est un code très court, mais vous pouvez voir que la fonctionnalité de ce code est sémantiquement divisée comme suit:

Dans le code d'origine, la fonctionnalité de mise en cache est réalisée par un dictionnaire d'arguments passé à la fonction web_lookup. En d'autres termes, la fonction elle-même est une implémentation qui intègre les fonctionnalités de la logique métier et de la logique administrative.

En revanche, dans un meilleur code, la fonction implémente uniquement la logique métier, et la logique administrative est implémentée par le décorateur fermé. En faisant cela, vous constaterez que la logique métier est clairement séparée et que le code est plus lisible et maintenable.

La quantité de code a augmenté avec l'implémentation des décorateurs, mais je pense que l'appeler "beau code" est un sentiment très pythonique.

À propos, ces modèles de décorateur de caisse sont des modèles standard, ce n'est donc pas difficile et vous devriez absolument l'essayer.

Au fait, je pense que le code de la diapositive de la conférence que j'ai citée est faux ... Je modifie donc le code que j'ai écrit ci-dessus. C'est le décorateur. Vous vous trompez, non? https://speakerdeck.com/pyconslides/transforming-code-into-beautiful-idiomatic-python-by-raymond-hettinger-1

Un autre exemple simple

Puis un autre.

Surtout lorsque vous utilisez 2.x et que le code de caractère de l'entrée est inconnu, je suis vraiment fatigué de gérer la chaîne de caractères, de décoder en quelque sorte, uni-kodo en quelque sorte, etc., donc dans le traitement interne, j'utilise chardet avec un décorateur Faisons tout unicode et traitons-le.

Cela peut être utile lors de l'écriture d'un petit outil.

import chardet

def unicode_conv(func):
    def wrapper(*args):
        f = lambda x: x.decode(chardet.detect(x)['encoding'])
        args = [f(arg) if type(arg) != unicode else arg for arg in args]
        return func(*args)
    return wrapper

def funcA(*args):
    for arg in args:
        print(repr(arg))

@unicode_conv
def funcB(*args):
    for arg in args:
        print(repr(arg))

funcA('shrubbery')
funcB('shrubbery')
funcB(u'shrubbery')

** Résultat d'exécution **

'shrubbery'
u'shrubbery'
u'shrubbery'

Recommended Posts

Comment utiliser le décorateur
Comment utiliser la fonction zip
Comment utiliser le module optparse
Comment utiliser le module ConfigParser
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Comment utiliser le pipeline Spark ML
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser Pandas 2
Comment utiliser Virtualenv
Comment utiliser pytest_report_header
[Linux] Comment utiliser la commande echo
Comment utiliser Bio.Phylo
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser IPython
Comment utiliser virtualenv
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser le dictionnaire {}
Comment utiliser Pyenv
Comment utiliser python-kabusapi
Comment utiliser le débogueur IPython (ipdb)
Comment utiliser le retour
Comment utiliser pyenv-virtualenv
Comment utiliser imutils
Comment utiliser la bibliothèque C en Python
Comment utiliser MkDocs pour la première fois
Comment utiliser la bibliothèque de dessins graphiques Bokeh
Comment utiliser l'API Google Cloud Translation
Comment utiliser l'API du guide des programmes NHK
[Algorithm x Python] Comment utiliser la liste
Comment utiliser Qt Designer
Comment utiliser la recherche triée
[gensim] Comment utiliser Doc2Vec
python3: Comment utiliser la bouteille (2)
Comprendre comment utiliser django-filter
[Python] Comment utiliser la liste 1
Comment utiliser FastAPI ③ OpenAPI
Comment utiliser IPython Notebook
Comment utiliser Pandas Rolling
[Note] Comment utiliser virtualenv
Python: comment utiliser pydub
[Python] Comment utiliser checkio
Comment faire fonctionner GeoIp2 de Django
[Python] Comment utiliser input ()
[Introduction] Comment utiliser open3d
Comment utiliser Python lambda
Comment utiliser Jupyter Notebook
[Python] Comment utiliser virtualenv
python3: Comment utiliser la bouteille (3)