Le problème est, au moment où le décorateur decorated
est appelé, il est aucun objet Blah
encore: l'objet de classe est construit après le corps de classe fin de l'exécution. Le plus simple est d'avoir decorated
stocker l'information "ailleurs", par ex. un attribut de fonction, puis un dernier passage (un décorateur de classe ou une métaclasse) récolte cette information dans le dictionnaire que vous désirez.
décorateurs de classe sont plus simples, mais ils ne sont hérités (donc ils ne viennent pas d'une classe parente) non, tandis que les métaclasses sont hérités - donc si vous insistez sur l'héritage, un métaclasse il devra être. Simplest-première, avec un décorateur de classe et la « liste » variante que vous avez au début de votre Q plutôt que la « dict » variante vous avez plus tard:
import inspect
def classdecorator(aclass):
decorated = []
for name, value in inspect.getmembers(aclass, inspect.ismethod):
if hasattr(value, '_decorated'):
decorated.append(name)
del value._decorated
aclass.decorated = decorated
return aclass
def decorated(afun):
afun._decorated = True
return afun
maintenant,
@classdecorator
class Blah(object):
def one(self):
pass
@decorated
def two(self):
pass
donne Construire un dict à la place, comme vous le demandez dans la deuxième partie de votre Q, signifie juste changer decorated.append(name)
à decorated[name] = value
dans le code ci-dessus, et bien sûr initialiser decorated
dans le décorateur de classe à un dict vide plutôt que d'une liste vide.
La variante metaclass utiliserait __init__
de la métaclasse pour effectuer essentiellement le même post-traitement après que le corps de classe est construit - __init__
de métaclasse obtient un dict correspondant au corps de classe comme son dernier argument (mais vous devrez soutenez vous-même l'héritage en traitant de manière appropriée la dictée ou la liste analogue d'une classe de base). Ainsi, l'approche de la métaclasse est seulement «un peu» plus complexe dans la pratique qu'un décorateur de classe, mais conceptuellement, il est ressenti comme étant beaucoup plus difficile par la plupart des gens. Je donnerai tous les détails pour la métaclasse si vous en avez besoin, mais je recommanderais de rester avec le décorateur de classe plus simple si possible.
Il n'y a pas de décorateurs de classe dans Python 2.6. –
Oui, il y en a. J'ai effectivement testé ces deux morceaux de code avant de les poster. Ils fonctionnent très bien en Python 2.6. –
si vous changez la version du décorateur de classe pour utiliser 'inspect.getmembers' comme dans ma réponse, il s'occupera de l'héritage - alors je peux supprimer ma réponse, car elle duplique la plupart du temps la vôtre (sans surprise ;-) mais la tienne est plus complète . –