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 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 **.
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.
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
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