10
votes

Décorateurs de python par rapport à la méthode "autour" close

Je suis revenu à mon clos (système d'objet LISP commun) pour cette question abstraite.

J'augmente la question à clarifier: em> p>

Il me semble qu'un décorateur de python est une sorte de méthode "autour" à Clos. p>

de ce que je me souviens, une méthode "autour" à Clos est une méthode / fonction qui enveloppe la méthode / la fonction principale du même nom. Il traverse également les sous-classes de haut en bas. EM> Voici une syntaxe (je viens d'attraper mon livre). P>

toutes ces méthodes em> Ceci Strike> serait à l'intérieur d'une classe: p> xxx pré>

Il peut y avoir des méthodes avant et après trop (que je jette une complétude) em> : p> xxx pré>

et enfin la méthode autour (remarquez ici que cette méthode semblait être comme un décorateur) em>: p> xxx PRE>

Je pense que la sortie serait: p> xxx pré>

J'ai toujours utilisé cette compréhension des classes et de leurs méthodes comme point de référence pour le développement de code. et malheureusement, peu de langues semblent aller aussi loin avec leur paramétrage et leur puissance de méthode. EM> P>

Je suis assez nouveau à Python et j'essaie de voir comment les décorateurs s'intégrent. Ils semblent un Petit lâche dans celui qu'un décorateur peut être une fonction complètement externe qui a pourtant la capacité de manipuler des informations dans les informations d'appel et même de modifier les variables d'instance et de classe de l'objet appelées, et de plus en plus qu'il semble préformer le rôle de la méthode autour comme indiqué ici. Mais j'espérais que quelqu'un puisse aider à expliquer la relation entre les décorateurs et autour des méthodes em>. Je pensais que quelqu'un aimerait vraiment que l'occasion de le faire. P>

Qu'est-ce qui rend plus puissant pour moi, c'est que vous pouvez avoir plusieurs héritages avec ces méthodes. Ainsi, une classe peut être constituée de superclasses contenant des fonctionnalités et des attributs distincts qui se manipulent. Ainsi, une méthode autour de l'une des superclasses pourrait terminer le débit (si «appel-next-méthode» n'est pas terminée), comme la façon dont un décorateur peut apparemment fonctionner. Est-ce que c'est la même chose qu'un décorateur ou différent? Dans une méthode autour, vous passez dans les mêmes arguments, mais à un décorateur, vous passez dans la "fonction" dans une définition stricte qui est augmentée. Mais le résultat est le même? Strong> p>

Merci beaucoup! Peut-être que quelqu'un pourrait montrer l'approximation de ce qui précède à Python. Fait appeler la méthode suivante. Strike> P>

Donc, le problème ne consiste pas à mettre en œuvre les méthodes de clos de Python, mais montrant la manière dont Python se rapproche de ce système de manière pythonique. Ou montrant comment Python est en fait meilleur que cela. Em> p>

C'est plus du genre d'exemple que je pensais: em> p> xxx

Si une instance de triangle a visible = FALSE, alors le rendu: autour de la méthode principale du triangle. em> p>

en d'autres termes le La chaîne d'appel de la méthode de rendu est (a) rendue: autour, b) Triangle primaire, (c) terminer le rendement: autour de. Si Triangle avait une méthode: après la méthode, elle serait appelée après primaire, puis la méthode autour de la finition terminée. Em> p>

Je comprends les difficultés d'utilisation de l'héritage par rapport à la création de modèles de conception plus récents Mais ici, j'essaie de combler mes connaissances. S'il y a un modèle de conception qui correspond aux décorateurs (plus précisément que le modèle de conception "décorateur"), ce serait formidable de comprendre également. Em> p>

Conclusions h1>

Je suis Obtenir la suspension des décorateurs. Mais je voulais présenter où je suis en train d'essayer d'imiter la traversée de la méthode de fermeture. Tout le monde m'a inspiré à l'essayer depuis que j'ai le livre et je me souviens bien de ça. Merci à tous pour toutes les grandes suggestions, ils sont tous un morceau du puzzle. En termes de mise en œuvre de la structure réelle dans un seul décorateur, se rapprochera et c'est ce qui a fonctionné pour le déplacer vers l'avant avec la découverte de la méthode dynamique (voir ci-dessous). J'ai créé un seul décorateur qui fait ce que je recherche et peut fonctionner sur n'importe quelle classe. Je suis sûr que cela pourrait être plus propre et il y a un problème que cela ne cherche que sur une superclasse et que cela fait des méthodes étrangement, mais cela fonctionne. P>

Python 2.6.4 (r264:75706, Mar  1 2010, 12:29:19)  
[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin  
Type "help", "copyright", "credits" or "license" for more information.  
>>> import cw  
>>> s= cw.subclass()  
>>> s.helloworld()  
Sub Around Start  
Aound Start  
Sub Before  
Baseclass Before  
Hello Sub World Fooey 2 barrey 7  
Baseclass After Fooey Now 4  
Sub After  
Around End  
Sub Around End  
>>> s.helloworld()  
Sub Around Start
Aound Start  
Sub Before  
Baseclass Before  
Hello Sub World Fooey 5 barrey 8  
Baseclass After Fooey Now 7  
Sub After  
Around End  
Sub Around End  
>>> s.helloworld()  
Sub Around Start  
Aound Start  
Sub Before  
Baseclass Before  
Hello Sub World Fooey 8 barrey 9  
Baseclass After Fooey Now 10  
Sub After  
Around End  
Sub Around End  
>>> s.helloworld()  
Sub Around Start  
>>Hey Barrey too big!  
Sub Around End  
>>> s.helloworld()  
Sub Around Start  
Aound Start  
>>FOOEY IS TOO BIG!!!  
Around End  
Sub Around End  
>>> s.helloworld()  
Sub Around Start  
Aound Start  
Sub Before  
Baseclass Before  
Hello Sub World Fooey -9 barrey -6  
Baseclass After Fooey Now -7  
Sub After  
Around End  
Sub Around End  
>>> s.helloworld()  
Sub Around Start  
Aound Start  
Sub Before  
Baseclass Before  
Hello Sub World Fooey -6 barrey -5  
Baseclass After Fooey Now -4  
Sub After  
Around End  
Sub Around End  
>>> s.helloworld()  
Sub Around Start  
Aound Start  
Sub Before  
Baseclass Before  
Hello Sub World Fooey -3 barrey -4  
Baseclass After Fooey Now -1  
Sub After  
Around End  
Sub Around End  
>>> b = cw.baseclass()  
>>> b.helloworld()  
Aound Start  
Baseclass Before  
Am I really so wee Before?  This method is not called on subclass but should be  
Hello World  
Baseclass After Fooey Now 5  
Around End  
>>> b.helloworld()  
Aound Start  
Baseclass Before  
Am I really so wee Before?  This method is not called on subclass but should be  
Hello World  
Baseclass After Fooey Now 9  
Around End  
>>> b.helloworld()  
Aound Start  
Baseclass Before  
Am I really so wee Before?  This method is not called on subclass but should be  
Hello World  
Baseclass After Fooey Now 13  
Around End  
>>> b.helloworld()  
Aound Start  
>>FOOEY IS TOO BIG!!!  
Around End  
>>> b.helloworld()  
Aound Start  
Baseclass Before  
Am I really so wee Before?  This method is not called on subclass but should be  
Hello World  
Baseclass After Fooey Now -6  
Around End  


13 commentaires

Je suis heureux que les autres s'attaquent à votre question directe, mais cette phrase s'en tient à sortir: "J'ai toujours utilisé cette compréhension des classes et de leurs méthodes comme point de référence pour développer le code". Cela me frappe comme un moyen très étrange d'approcher OO. Si vous envisagez d'encapsulation, de sous-classement, etc. En termes de décorateurs et de «avant» et de «après», je vous suggérerais de manière aussi poliment que vous avez une autre chose à aller sur les concepts. De tels décorateurs inhabituels devraient apparaître très rarement, le cas échéant, dans une architecture typique de OO.


Merci dedthinking. J'ai réalisé, examiner les réponses ci-dessous (travaillant toujours sur la compréhension des décorateurs, en particulier dans Django, et quand les utiliser), qu'il y a un autre élément de l'image ci-dessus que je n'avais pas inclus sur Clos. Je vais éditer ce qui précède pour clarifier ce que sont ces méthodes. Je pense que ça va aussi secouer les réponses ci-dessous. Fondamentalement, au ferme toutes ces méthodes définies ci-dessus font partie d'une seule classe. Donc, dans ce cas de base, ces méthodes pourraient être représentées par une méthode / une fonction. Ce n'est que lorsque la sous-classement est intéressante.


Ok, donc j'ai construit quelque chose d'intérêt pour la communauté python teeny / ferme. Mais il est basé sur les conclusions de ce fil. Où dois-je le dire?


code.AcreState.com/Recipes est un lieu standard. Je m'intéresse depuis que des décorateurs, des métaclasses (que je suppose que vous avez utilisé) et que l'héritage est un pita.


Oh, en fait @Richard, je ne savais pas où le mettre dans le site ici, mais je suppose que je viens d'étendre ma question initiale comme si je l'ai fait au-dessus de la section "Conclusion". (Un peu de lecture Google Wave serait pratique). Mais je suppose que je pourrais le mettre là-bas. C'est définitivement dans un état rudimentaire. En ce qui concerne les métaclasses, je ne les ai pas utilisées à Python. Je ne pense pas. Je suis peut-être sans le savoir? Obtenu un lien?


hehe ... vous sauriez si vous utilisiez des métaclasses :) (et non, vous n'êtes pas dans le code ci-dessus). Une recherche sur Google de "Métaclasses Python" est vraiment le meilleur point de départ. Quoi qu'il en soit, oui, ce décorateur ressemble à ce que vous voulez. Il y a quelques notes de code (vous pouvez utiliser getattr (obj, nom, par défaut ) sans essayer / sauf, et que le décorateur accepte des arguments afin que vous n'ayez pas besoin de respecter le _After , _arning nommage, le newfunc def pourrait simplement être inliné, pourrait utiliser Essayer / enfin pour le _after), mais sinon cela ressemble à ce que vous voulez.


La seule raison pour laquelle j'ai même mentionné des classes méta, c'est que vous pourriez configurer tous les éléments avant / après / après / autour de la «compilation», plutôt que de devoir la regarder au moment de l'exécution. En effet, le code utilisé pour la fabrication de classes méta est exécuté lorsque la classe est définie (similaire à la manière dont un décorateur est exécuté lorsque la fonction est définie). Dans les versions ultérieures de Python, il existe des décorateurs de niveau de classe, ce qui pourrait être plus facile que les classes méta. En tout état de cause, bon travail :)


@Richard merci! J'ai regardé les métaclasses. Les concepts que j'essayent de jeter à Python ici sonnent définitivement comme une question de métaclass maintenant! Créer un beau "clostype" métaclass me donnerait le concept de décorateur ci-dessus sans le décorateur non? Question: Je suis toujours limitée à la création d'une syntaxe personnalisée (droite?) Ce qui signifie que les noms de ces "méthodes partielles" auraient toujours besoin d'être là (voir originale DEFMETHODS en haut pour la syntaxe close). Les Python 2 ou 3 ont également quelque chose comme le paradigme que j'ai décrit? Diriez-vous que les décorateurs et les métaclasses peuvent donc être vraiment un bricolage?


Son bricolage, mais ce n'est pas un bricolage facile. Non, vous ne pouvez pas créer de syntaxe personnalisée, vous êtes toujours limité à l'utilisation de la syntaxe Python. Au lieu de _Before, vous pouvez attribuer un attribut à la fonction ( func.before = avant ) étant enveloppé (les fonctions sont des objets comme tout, vous pouvez donc ajouter des attributs) ou utiliser une fermeture (comme ça dans la réponse acceptée).


D'accord. Donc, l'astuce là-bas pour ajouter des attributs aux fonctions est d'éviter toute écrasement des fonctions avec le même nom que celui utilisé à Clos avec les arguments: AVANT,: APRÈS,: autour de. Donc, si j'avais def MyMethod répété dans le code, le dernier def clouerait le premier, oui? Donc, ci-dessus, la création de noms différents pour les fonctions est nécessaire hein? Ce que je pouvais faire, c'est que la métaclasse recherche ces fonctions. Une chose que je n'aime pas à propos de la mienne est la voie est cassée en plusieurs parties ... Je vais essayer de faire d'autres modifications suggérées ci-dessus. J


@Richard. Je ne suis pas clair sur la façon de faire en sorte que Newfunc ...


Je ne sais pas ce que vous entendez par une fonction du même nom étant encombré. Si vous donnez une fonction le même nom que d'un autre dans la même classe, oui, il sera classé. Si vous voulez dire, vous nommez une fonction identique à celle d'une classe mère, il va masquer le parent (bien qu'il soit toujours accessible en utilisant Super ()))


Ouais. Parce que dans Lisp, ils ne sont pas classés: vous pouvez (Defmethod Helloworld () ()) et (Defmethod Helloworld: Avant () ())), etc. Ils sont les mêmes méthodes, mais les arguments et le protocole différencient les deux de les clobber. C'est pourquoi dans mon code, j'ai utilisé le "_ avant" concaténé à la fonction, de sorte qu'ils ne seraient pas encombrés.


4 Réponses :


2
votes

Voici une mise en œuvre rapide et sale une implémentation légèrement meilleure (maintenant avec la méthode autour, espérons-le, dans les bons endroits), à l'aide de décorateurs xxx

appelant fn () résulte de la présente: xxx

Les décorateurs dans ce cas peuvent être un peu déroutant, car il y a deux imbriqué Fonctions impliquées dans chaque, plutôt que la seule fonction imbriquée dans beaucoup de décorateurs.

Ce n'est peut-être pas aussi élégant que la version proche (et je risquerais de manquer certaines de ses fonctionnalités), mais il semble faire ce que vous voulez.


10 commentaires

@Will, merci pour l'exemple et l'exemple révisé! Je pense que cela va certainement m'aider à ajuster ma cartographie cognitive de la programmation pour inclure cette construction! Maintenant, je vais l'analyser plusieurs fois et voir si ça va s'asseoir dans mon cerveau.


En principe, ce n'est pas loin, mais vous n'avez pas manipulé des exceptions ni la manière dont autour de est censé pouvoir également poster des résultats post-traiter. Pas impossible de travailler, mais un peu désordonné. (Vous pouvez implémenter avant et après en termes de autour de , si cela facilite la tâche ...)


Remarque pour la perspective Close: Dans une hiérarchie de classe, la méthode sur laquelle: autour de la classe est appelée en premier (ce qui signifie que l'objet d'instance: sur la méthode). Il monte alors à la superclasse pour appeler la prochaine méthode. Il fait alors la même chose pour: avant de commencer avec la plus spécifique à nouveau. Ensuite, il appelle la méthode principale. Puis le plus spécifique: après des méthodes. Une fois que cela joue, il se déplacerait dans des méthodes autour des méthodes qui avaient un code après la méthode appelée. (Cela diffère de ce qui précède en ce que les "Befores" sont appelés avant les méthodes autour. Je ne sais pas encore les sous-classes.)


@Donal & @ijames, ouais, j'étais sûr que cette mise en œuvre pâlirait par rapport à la mise en œuvre de Clos Clos. J'espérais simplement que cela illustrerait une approche pour utiliser des décorateurs pour accomplir quelque chose de similaire dans le principal (comme vous l'avez souligné). Hors de curiosité, comment vous attendriez-vous des exceptions à traiter par ces décorateurs et comment la méthode autour de pouvoir poster les résultats?


Et je mettez à jour mon exemple pour appeler les fonctions autour du bon endroit, je pense. C'était juste une surveillance stupide de ma part.


Votre méthode autour de ne capture pas tout à fait l'essence de ce qui est capable de. Voir mon exemple ci-dessous. Un rappel peut être transmis à la fonction de décoration qui exécute la fonction exactement où vous souhaitez exécuter. Comme Donal Fellows a dit, vous pouvez implémenter avant et après en termes de autour de


@Donal, à droite, il semble que un décorateur aussi peut également gérer le post-traitement en plus du pré-traitement et peut même sauter "appel-méthode appelant" qui, avec des décorateurs, est de ne pas renvoyer aucun aspect de la méthode d'origine. ? Je pense que des exceptions sont locales aux fonctions individuelles. La commande d'exécution n'est donc pas affectée par un cadre d'exception. Des exceptions particulières pourraient modifier le flux de méthodes autour, mais ne pouvaient rien faire avant et après des méthodes. D'après ce que je peux dire, ce type de fragment de fonction (avant et après) ne fait pas partie de Python.


Peut-être que c'est des pommes et des oranges ici? Un décorateur est une classe complètement séparée de la chose décorée. Alors qu'une méthode autour est une méthode polymorphe de la même classe ou de la même classe ou de la sous-classe. Alors sont-ils simplement trop différents pour comparer?


Ok, je commence à avoir une compréhension plus profonde ici. Question sur appelable et instanciation. Question appelable d'abord. Premièrement, que si ces méthodes sont vérifiées n'étaient pas encore appelables? Étant donné que l'emballage semble être une macro, le "appelable" est appelé tôt. Et si les méthodes ont souligné n'existent pas?


En outre, j'essaie d'envisager ce qui précède comme une classe. Donc, au lieu d'avoir ces méthodes flottant là-bas, ils sont dans une classe. Et au lieu d'avoir absolument nommé des méthodes, elles sont éteintes de la méthode principale. Donc, la méthode helloworld () serait accompagnée de def helloworld_before (), helloworld_after () et helloworld_arond (). Hmmm je pense que je suis proche. Je cherche un moyen d'utiliser getattr (instance, Func .__ Nom__ + "_Brefore) ou quelque chose comme ça pour que l'enveloppe / décorateur fait tout ...



0
votes

Je ne suis pas sûr de comprendre : autour de code>, : avant code> et : après code> très bien, mais c'est quelque chose comme ça que tu es ce que tu es Vous recherchez?

# Enter around
# Before
# Hello World
# After
# Exit around around


1 commentaires

Outre les multiples classes, cela capture un aspect de la capacité de ferme qui est un flux d'exécution. Mais il y a quelques problèmes que je vois. Tout d'abord, c'est que seule la méthode principale la plus spécifique (FOO's Helloworld) devrait être appelée. Donc, je penserais que c'est: autour, avant, foo, après. Mais la façon dont vous avez représenté autour de vous, comparé à l'avant et après nous rapprocher, et il démontre la capacité de traverser l'arbre de héritage. Mais pourrait-il être fait tout dans une classe? Et comment cette méthode se compare-t-elle à un décorateur Python Python? Merci!




2
votes

Inspiré de la question originale et de tout ce que divers brouillons, j'ai mis en œuvre de près / après / après les méthodes auxiliaires Python Module.

Voir: http://code.activestate.com / Recettes / 577859-Côté de forme à côte arrière-Feinfor-Auxiliaire-Méthodes /

Je l'ai fait en utilisant quelques fonctions de python natif :

  • classe et fonction décorateurs ,
  • classe héritage plus le Super () fonction intégrée ,
  • Nom privé Mangling (aux utilisateurs libres de nécessité de nom de classe redondant RETYAGE).

1 commentaires

Je suis excité de jeter un coup d'oeil à ça!