J'ai un décorateur comme ci-dessous.
def myDecorator(test_func):
return callSomeWrapper(test_func)
def callSomeWrapper(test_func):
return test_func
@myDecorator
def someFunc():
print 'hello'
Je souhaite valoriser ce décorateur pour accepter un autre argument comme ci-dessous
def myDecorator(test_func,logIt):
if logIt:
print "Calling Function: " + test_func.__name__
return callSomeWrapper(test_func)
@myDecorator(False)
def someFunc():
print 'Hello'
Mais ce code donne l'erreur,
TypeError: myDecorator () prend exactement 2 arguments (1 donné)
Pourquoi la fonction n'est-elle pas automatiquement transmise? Comment passer explicitement la fonction à la fonction décorateur?
Réponses:
Puisque vous appelez le décorateur comme une fonction, il doit renvoyer une autre fonction qui est le décorateur réel:
La fonction externe recevra tous les arguments que vous transmettez explicitement et doit renvoyer la fonction interne. La fonction interne recevra la fonction à décorer et retournera la fonction modifiée.
En général, vous voulez que le décorateur modifie le comportement de la fonction en l'enveloppant dans une fonction wrapper. Voici un exemple qui ajoute éventuellement la journalisation lorsque la fonction est appelée:
L'
functools.wraps
appel copie des éléments comme le nom et la docstring dans la fonction wrapper, pour la rendre plus similaire à la fonction d'origine.Exemple d'utilisation:
la source
functools.wraps
est conseillée - elle conserve le nom d'origine, docstring, etc. de la fonction encapsulée.myDecorator
ici) un décorateur. Ceci est pratique pour un utilisateur du décorateur, mais peut être déroutant lorsque vous essayez d'en écrire un.log_decorator
prend un argument par défaut, vous ne pouvez pas l'utiliser@log_decorator
, il doit l'être@log_decorator()
Juste pour fournir un point de vue différent: la syntaxe
est équivalent à
En particulier,
expr
peut être tout ce que vous voulez, à condition qu'il soit évalué à un appelable. En particulier ,expr
peut être une usine de décorateurs: vous lui donnez quelques paramètres et cela vous donne un décorateur. Alors peut-être qu'une meilleure façon de comprendre votre situation est dequi peut ensuite être raccourci en
Bien sûr, comme il ressemble à
decorator_factory
un décorateur, les gens ont tendance à le nommer pour refléter cela. Ce qui peut être déroutant lorsque vous essayez de suivre les niveaux d'indirection.la source
Je veux juste ajouter une astuce utile qui permettra de rendre les arguments du décorateur optionnels. Cela permettra également de réutiliser le décorateur et de diminuer l'emboîtement
la source
Juste une autre façon de faire des décorateurs. Je trouve que c'est la façon la plus simple de comprendre ma tête.
la source
Maintenant, si vous voulez appeler une fonction
function1
avec un décorateurdecorator_with_arg
et dans ce cas, la fonction et le décorateur prennent des arguments,la source