6
votes

Définition d'une métaclasse de classe à l'aide d'un décorateur

suivant Cette réponse semble que la métaclasse d'une classe peut être modifiée après la définition de la classe en utilisant ce qui suit *: xxx pré>

définir une fonction p> xxx pré>

me permet d'appliquer un décorateur à une définition de classe similaire, P>

class B(object):
    __metaclass__ = MyMetaClass
    pass


0 commentaires

3 Réponses :


2
votes

Mon résumé de votre question: "J'ai essayé une nouvelle façon délicate de faire une chose, et cela n'a pas bien fonctionné. Devrais-je utiliser la solution simple à la place?"

Oui, vous devriez le faire de manière simple. Vous n'avez pas dit pourquoi vous êtes intéressé à inventer une nouvelle façon de le faire.


1 commentaires

Je me demandais simplement s'il y avait un décorateur équivalent à définir le __ métaclass __ dans une définition de classe. Je suppose qu'une autre partie de ma question est que mon "décorateur" a fait semble au travail, mais j'ai remarqué que la classe décorée n'a pas __ métaclass __ , donc il y a clairement une différence entre les deux méthodes; Pourquoi est-ce?



1
votes

La classe n'a pas de __ métaclass __ code> Set d'attribut ... Parce que vous ne le réglez jamais!

Quelle métaclasse à utiliser est normalement déterminée par fort> Nom __ METACLASS__ code> défini dans un bloc de classe. L'attribut __ métaclass __ code> n'est pas défini par la métaclasse. Donc, si vous invoquez une métaclasse directement plutôt que de régler __ métaclass __ code> et de laisser python la figure, alors aucun __ métaclass __ code> est défini. P>

En fait, normal Les classes sont toutes des instances de la métaclass type code>, donc si la métaclasse définit toujours le __ métaclass __ code> sur ses instances alors chaque classe em> aurait un __ METACLASS __ CODE> Attribut (la plupart d'entre eux définis sur TYPE CODE>). P>


Je n'utiliserais pas votre approche de décorateur. Il obscurcit le fait qu'une métaclasse est impliquée (et laquelle) est toujours une ligne de chaudière, et il est simplement en désordre pour créer une classe à partir des 3 fonctionnalités définissant (nom, bases, attributs) code> Seulement pour tirer ces 3 bits de la classe résultante, jeter la classe à l'extérieur et faire une nouvelle classe à partir de ces mêmes 3 bits! p>

Lorsque vous faites cela dans Python 2.x: P>

attrs = {}
attrs['__metaclass__'] = MyMeta
def __init__(self):
    pass
attrs['__init__'] = __init__
A = attrs.get('__metaclass__', type)('A', (object,), attrs)


0 commentaires

6
votes

Certes, je suis un peu en retard à la fête. Cependant, j'ai chuté cela valait la peine d'être ajouté.

Ceci est complètement faisable. Cela étant dit, il y a beaucoup d'autres moyens d'accomplir le même objectif. Toutefois, la solution de décoration, en particulier, permet une évaluation différée ( obj = déc (obj) code>), qui utilise __ métaclass __ code> à l'intérieur de la classe. Dans le style de décorateur typique, ma solution est ci-dessous. P>

Il y a une chose délicate que vous puissiez rencontrer si vous construisez simplement la classe sans changer le dictionnaire ou de copier ses attributs. Tout attributs que la classe avait précédemment (avant décoration) semble manquer. Donc, il est absolument essentiel de les copier puis de les modifier, puis que j'ai dans ma solution. P>

Personnellement, j'aime pouvoir garder une trace de la manière dont un objet a été enveloppé. Donc, j'ai ajouté l'attribut __ __ code>, qui n'est pas strictement nécessaire. Il en fait aussi plus que functools.wraps code> à Python 3 pour les classes. Cependant, cela peut être utile avec l'introspection. De plus, __ métaclass __ code> est ajouté pour agir davantage comme le cas d'utilisation de la métaclasse normale. P> xxx pré>

pour un exemple trivial, prenez les suivants. P> xxx pré>

ceci donne le bon résultat ... p> xxx pré>

Utilisation du décorateur moins habituel, mais identique ... P>

|1> Test.passed
|.> True


1 commentaires

Si cela est utile, faites-le dans le paquet Metawrap sur PYPI. Les commentaires sur le repo GitHub sont les bienvenus. :) ref: pypi.org/project/metawrap ref: GITUB.COM/JAKIRKHAM/METAWRAP