J'essaie de déterminer comment utiliser des décorateurs sur des sous-classes utilisant La sortie doit être: p> Est-ce que quelqu'un sait un moyen de ne pas casser une sous-classe qui utilise < Code> Super () Code> Lorsque vous utilisez un décorateur? Idéalement, je voudrais réutiliser une classe de temps en temps et simplement le décorer avec la casser. P> P> super () code>. Étant donné que mon décorateur de classe crée une autre sous-classe une classe décorée semble empêcher l'utilisation de
Super () code> lorsqu'il modifie le nom code> transmis sur
super (classname, auto) < / code>. Ci-dessous est un exemple:
5 Réponses :
Êtes-vous sûr de vouloir utiliser un décorateur de classe et non simplement héritage? Par exemple, au lieu d'un décorateur de remplacer votre classe avec une sous-classe introduisant certaines méthodes, vous souhaitez peut-être une classe de mixine et utiliser plusieurs héritages pour créer la classe finale?
Ceci serait accompli par quelque chose comme P> < Pré> xxx pré> p>
J'ai vraiment aimé cette solution. J'utilise quelques décorateurs de classe qui prennent un paramètre (permission), cependant. Je pourrais utiliser le mélange pour changer les paramètres init b>, mais je pense que je préfère la flexibilité de l'ajout @Decorator (Perm) à la classe au lieu de devoir changer mon code quand je veux une classe avec le paramètre permission. Je peux utiliser cela au lieu d'autres décorateurs!
En raison de métaclasses, il est techniquement possible d'utiliser des mélanges pour n'importe quoi i> Vous pouvez utiliser un décorateur de classe pour. De manière générale, j'utilise des mixines si je veux ajouter des méthodes à une classe et j'utilise des décorateurs de classe lorsque je ne veux pas vraiment muter une classe du tout, mais simplement l'enregistrer ou quelque chose comme ça.
Merci, Mike! Cela ressemble à une bonne méthodologie. Comment passerais-je la permission au mixin? Est-ce que je ferais une propriété de la sous-classe lorsque je le déclare?
Fondamentalement, vous pouvez voir le problème après avoir entré votre échantillon de code à l'invite de Python interactif: c'est-à-dire, le nom Vous pouvez reproduire le même problème très simplement sans décoration, juste en ayant une sous-classe USURP son nom de classe de base: p> maintenant, Solutions de contournement - Si vous devez absolument avoir la décoration de classe comme usurpation (pas seulement la décoration de classe par des modifications de l'argument de classe reçu), sous-classe code> est maintenant lié (dans Global Portée, dans ce cas) à une classe qui, en fait,
sous-classe code>, mais une sous-classement de celui-ci. Donc, toute référence reliée tardive à ce nom, comme celle que vous avez dans son
Super (sous-classe, code> Appelez, fera bien sûr la sous-classe qui se masquait de ce nom - que la superclasse de la sous-classe est bien sûr "Le vrai
sous-classe code>", d'où la récursion infinie. p>
sub (). PCL () code> causera une récursion infinie, en raison de "nom d'usurpation". Décoration de classe, à moins que vous n'utilisez-le à Décorer et retourner la même classe que vous obtenez en tant qu'argument, est systématique "nom d'usurpation" systématique et incompatible avec les utilisations du nom de la classe qui doit absolument renvoyer la classe "vraie" de ce nom, et non l'usurveur (être que dans auto code> ou autrement). p>
Super code> - Besoin essentiellement des protocoles de coopération entre l'usurvateur et l'usurvateur possible, tels que les petits changements suivants à votre exemple code: P>
def class_decorator(cls):
class _DecoratedClass(cls):
_thesuper = cls
def __init__(self):
return super(_DecoratedClass, self).__init__()
return _DecoratedClass
...
@class_decorator
class SubClassAgain(BaseClass):
def print_class(self):
cls = SubClassAgain
if '_thesuper' in cls.__dict__:
cls = cls._thesuper
super(cls, self).print_class()
Comme vous le savez peut-être déjà, le problème provient du fait que le nom sous-classe code> dans
sousclassagain.print_class code> est soumis à l'espace de noms global du module actuel.
Sous-classe Code> fait donc référence à la classe
_DecoratedClass code> plutôt que la classe qui est décorée. Une façon de se rendre à la classe décorée est de suivre une convention que les décorateurs de classe ont une propriété faisant référence à la classe décorée.
def class_decorator(cls):
old_init = getattr(cls, '__init__')
def __init__(self, *args, **kwargs):
print 'decorated __init__'
old_init(self, *args, **kwargs)
setattr(cls, '__init__', __init__)
return cls
Le décorateur crée une sorte de situation de héritage de diamant. Vous pouvez éviter ces problèmes en n'utilisant pas Super () code>. Changer
sous-classe code> sur ce qui suit empêchera la récursion infinie:
Merci pour votre réponse! J'ai sélectionné cette réponse car il ne coule pas la sous-classe avec le décorateur. Je me rends compte que ma question était de savoir comment utiliser Super (), mais je suppose que la réponse est de ne pas le faire.
Que diriez-vous simplement de promouvoir _DecoratedClass code> 'S
__ bases __ code> jusqu'à la
__ bases __ code> de
sous-classe code>?
def class_decorator(cls):
class _DecoratedClass(cls):
def __init__(self):
return super(_DecoratedClass, self).__init__()
_DecoratedClass.__bases__=cls.__bases__
return _DecoratedClass