Je suppose que c'est comme ça qu'elles sont appelées, mais je vais donner des exemples au cas où.
Classe de décorateur: p> Fonction de décorateur: p> def decorator(func):
def wrapper(*args, **kwargs):
print 'something'
return func(*args, **kwargs)
return wrapper
3 Réponses :
Si vous pouvez écrire une fonction pour implémenter votre décorateur, vous devez le préférer. Mais tous les décorateurs ne peuvent pas être facilement écrits en fonction de la fonction - par exemple lorsque vous souhaitez stocker un état interne.
class counted(object): """ counts how often a function is called """ def __init__(self, func): self.func = func self.counter = 0 def __call__(self, *args, **kwargs): self.counter += 1 return self.func(*args, **kwargs) @counted def something(): pass something() print something.counter
Bien sûr, cela peut i> être écrit en fonction de la fonction. Mais dans Python, vous préférez généralement une classe sur une fermeture pour masquer l'état.
En fait, j'aime la version python (3.x) de ceci (utilise des bretelles * SOB * car les commentaires mangent des pauses de ligne): def compté (f) {x = 0; DEF Wrapper (* args, ** kwargs) {non local x; x + = 1; F (* args, ** kwargs)} retour wrapper} code>. La version 2.x est laid laide tout à fait la nature (piratage autour du manque de
non local code> avec l'utilisation d'une liste singleton et en utilisant son élément unique).
Vous pouvez également utiliser un attribut de la fonction wrapper pour maintenir le compteur.
@Delnan: Yeah, non utile code> est très utile, mais dans py2, vous pouvez également écrire
def enveloppé (...): enveloppé.Counter + = 1; ... code> dans le décorateur (les fonctions sont mutables aussi). Je ne peux pas vraiment penser à un bon exemple pour ma réponse; Imaginez simplement quelque chose de plus compliqué ;-)
Ce n'est généralement qu'une question de goût. La plupart des programmes Python utilisent la dactylographie du canard et ne se soucient pas vraiment de savoir si la chose qu'ils appellent est une fonction ou une instance d'un autre type, tant qu'elle est appelable. Et tout ce qui avec un Il y a quelques avantages à utiliser des décorateurs de type fonction: p>
beaucoup plus propre lorsque votre décorateur ne renvoie pas une fonction d'emballage (c'est-à-dire, il renvoie la fonction d'origine après quelque chose, comme définition d'un attribut). P> LI>
Pas besoin d'enregistrer explicitement la référence à la fonction d'origine, car cela se fait par la fermeture. p> li>
la plupart des outils qui vous aident à créer des décorateurs, tels que Il peut y avoir des programmes quelque part qui n'utilisent pas de dactylographie de canard, mais attendez-vous à un type de fonction, ce qui renvoie une fonction pour remplacer une fonction est théoriquement "plus sûre". P> LI >
ul>
Pour ces raisons, j'utilise la plupart du temps des décorateurs de style de fonction. En tant que contre exemple, toutefois, Ici est une récente instance dans laquelle le décorateur de style de classe était plus naturel pour moi. P> __ appel __ () code> est appelable. P>
functools.arraves () code> ou Michele Simionato's Signature PRESERVING'S> Decorator code> Module, fonctionnent avec la fonction Décorateurs de style. P> li>
functools.arras () code> peut être destiné à fonctionner avec des décorateurs de type fonction, mais
functools.update_wrapper (auto, enveloppé) code> dans le
__ init __ code> de Un décorateur de style de classe fonctionne parfaitement bien.
La mise en œuvre de la décoratrice de classe proposée a une légère différence avec la mise en oeuvre de la fonction: elle échouera sur des méthodes augmentera Pour ajouter prise en charge des méthodes, vous devez implémenter le va produire < / p> classe B: ... p> La raison pour laquelle cela fonctionne est que lorsque vous accédez au pour conclure, à condition de définir le typeError: myMethod () MyMethod () 1 Argument de positionnement requis: " auto ' code> p>
__ obtenez __ code> p>
B (). MyMethod code>, le
__ obtenir __ code> est appelé premier et fournit la méthode liée. Alors
__ appel __ p> est appelé p>
__ obtenir __ code>, la mise en œuvre de la classe et de la fonction peut être utilisé de la même manière. Voir Python Recoke Recette 9.9 pour plus d'informations. P> P>
Il y a une différence. La différence est exactement la même lorsque vous voudriez utiliser une fonction régulière par rapport à une classe normale