La mise en œuvre du décorateur modèle en Python
Je veux mettre en œuvre les décorateur modèle en Python, et je me demandais si il y a une façon d'écrire un décorateur qui vient de implémente la fonction qu'il souhaite modifier, sans avoir à écrire de la chaudière-plaque pour toutes les fonctions qui sont simplement transmis à l'objet décoré. Comme:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print "decorated f1"
self._decoratee.f1()
def f2(self): # I would like to leave that part out
self._decoratee.f2()
Je voudrais avoir des appels à foo_decorator.f2
transmis à decoratee.f2
automatiquement. Est-il possible d'écrire une méthode générique qui transfère toutes les mises au placard de la fonction-les appels à decoratee
?
- Pouvez-vous donner un exemple où tout simplement sous-classement, pas de travail? Vous pouvez sous-classe dynamiquement trop - ce modèle semble comme une solution de contournement pour les langues qui ne peuvent pas le faire ou ne prennent pas en charge plusieurs part de l'héritage.
- Je veux décorer des objets lors de l'exécution. Je veux appliquer différents décorateurs d'un objet et d'être en mesure de les supprimer. Sous-classement ne peut pas changer l'instance après qu'il a été créé, ou peut-il?
- Si vous avez de la classe
A
et changementA
, c'est à dire l'ajout d'une nouvelle méthode,A.foo = lambda self: self
cela vous permettra de réfléchir sur toutes les instances d'Un .. parce que tout est déterminé au moment de l'exécution. Excellente façon de produire absolument difficile à maintenir le code. - Le décorateur modèle (contrairement à python décorateurs) est utilisé pour ajouter un comportement à un objet lors de l'exécution. C'est en fait très facile à gérer, quand il est fait correctement, c'est pourquoi j'ai posté cette question. Je voulais trouver le moyen de cette en Python.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser
__getattr__
:__str__
.Comme un additif à Philipp réponse; si vous avez besoin non seulement de décorer, mais de préserver la type d'un objet, Python permet à la sous-classe d'une instance au moment de l'exécution:
C'est un peu plus complexe que ce qui est strictement nécessaire pour votre exemple, où vous savez que la classe d'être décoré à l'avance.
Ce pourrait suffire:
decoratee
, ce qui est probablement ce n'est pas souhaitée.C'est sans doute pas la meilleure pratique, mais vous pouvez ajouter des fonctionnalités à des instances, comme je l'ai fait pour aider à la transition de mon code à partir de l'ORM de Django à SQLAlachemy, comme suit:
Le diagramme UML dans la Wikipedia article est faux et est donc votre code.
Si vous suivez le "pattern décorateur", le décorateur classe est dérivée à partir de la base décorée de classe. (Dans le diagramme UML est un héritage de la flèche à partir de la WindowDecorator à la Fenêtre est manquant).
avec
vous n'avez pas besoin de mettre en œuvre sans décor méthodes.
BTW: Dans les langages à typage fort, il est une raison de plus pourquoi le décorateur doit être dérivée de la salle de classe: Sinon vous ne seriez pas en mesure de la chaîne de décorateurs.
Pour compléter @Alec Thomas réponse. J'ai modifié sa réponse à suivre le pattern décorateur. De cette façon, vous n'avez pas besoin de connaître la classe que vous soyez à la décoration à l'avance.
Ensuite, vous pouvez l'utiliser comme:
Dans un de mes projets, j'ai aussi besoin de faire une chose en particulier, c'est que même l'objet sous-jacent doit donc exécuter la méthode qui a été réimplémentée dans le décorateur. Il est en fait assez facile à faire si vous savez où la cible.
Le cas d'utilisation est:
Il est possible d'atteindre ce comportement comme ceci:
Cela peut ne pas fonctionner hors de la boîte que j'ai tapé tout le reste en dehors de la getattr méthode à partir du haut de ma tête.
Le code ressemble à la demande de l'attribut dans l'objet décoré, et si c'est une méthode (ne fonctionne pas pour les propriétés à présent, mais le changement de support ne devrait pas être trop difficile), le code puis tire la fonction réelle de la méthode et de l'utilisation du descripteur d'interface d'invocation il "relie" la fonction comme une méthode, mais d'un décorateur. Alors il est retourné et probablement exécuté.
L'effet de ceci est que si
b
jamais les appelsa
sur l'objet d'origine, puis, quand vous avez de l'objet décoré et il est tout appel de méthode en provenance du décorateur, le décorateur permet de s'assurer que toutes les méthodes d'accès sont liés à des le décorateur au lieu de cela, donc à la recherche de choses à l'aide de la décoratrice et pas l'objet d'origine, donc les méthodes spécifiées dans le décorateur prioritaires.P. S.: Oui, je sais, il ressemble plutôt à la succession, mais cette façon de faire dans le sens de la composition de plusieurs objets.