Peut un Python décoratrice d'une méthode d'instance accéder à la classe?
Salut j'ai quelque chose à peu près comme suit. Essentiellement, j'ai besoin d'accéder à la classe d'une méthode d'instance à partir d'un décorateur utilisé sur la méthode d'instance dans sa définition.
def decorator(view):
# do something that requires view's class
print view.im_class
return view
class ModelA(object):
@decorator
def a_method(self):
# do some stuff
pass
Le code que-est donne
AttributeError: 'function' object has no attribute 'im_class'
J'ai trouvé la même question/réponses - Python décorateur fait la fonction oubliez pas qu'il appartient à une classe et Obtenez de classe en Python décorateur - mais ceux-ci dépendent d'une solution de contournement qui saisit l'instance au moment de l'exécution en arrachant le premier paramètre. Dans mon cas, j'ai appeler la méthode basée sur l'information recueillie à partir de sa classe, donc je ne peux pas attendre un appel pour venir en.
Merci.
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez Python 2.6 ou version ultérieure, vous pouvez utiliser une classe décorateur, peut-être quelque chose comme ceci (attention: le code non testé).
La méthode décorateur marques de la méthode que celle qui est d'intérêt par l'ajout d'un "use_class" attribut - les fonctions et les méthodes sont aussi des objets, de sorte que vous pouvez ajouter des métadonnées.
Après la classe a été créée la classe décorateur passe alors par tous les moyens et tout ce qui est nécessaire sur les méthodes qui ont été marqués.
Si vous voulez toutes les méthodes pour être affecté ensuite, vous pouvez quitter le mode décorateur et il suffit d'utiliser la classe décorateur.
inspect.getmro(cls)
pour traiter toutes les classes de base dans la classe décorateur à l'appui de l'héritage.cls.__dict__
? de la première à obtenir la mro des classes, puis itérer sur eux et necls.__dict__
pour chaque?inspect
à la rescousse stackoverflow.com/a/1911287/202168Comme d'autres l'ont souligné, la classe n'a pas été créé au moment le décorateur est appelé. Cependant, il est possible d'annoter la fonction de l'objet avec le décorateur paramètres, puis re-décorer la fonction dans la métaclasse est
__new__
méthode. Vous aurez besoin pour accéder à la fonction de__dict__
attribut directement, au moins pour moi,func.foo = 1
a entraîné une AttributeError.setattr
devrait être utilisé au lieu d'accéder à__dict__
Comme Marque suggère:
Ce code montre comment cela peut fonctionne en utilisant automatique de post-traitement:
La sortie des rendements:
Notez que dans cet exemple:
Espère que cette aide
Comme les Fourmis, vous ne pouvez pas obtenir une référence à la classe à partir de l'intérieur de la classe. Toutefois, si vous êtes intéressé à faire la distinction entre les différentes classes ( pas de la manipulation de la classe réelle de type objet), vous pouvez passer une chaîne de caractères pour chaque classe. Vous pouvez également passer tous les autres paramètres vous aimez le décorateur à l'aide de la classe de style décorateurs.
Imprime:
Aussi, voir Bruce Eckel page sur les décorateurs.
@decorator('Bar')
par opposition à@Decorator('Bar')
.Le problème est que lorsque le décorateur est appelé la classe n'existe pas encore. Essayez ceci:
Ce programme permettra de sortie:
Comme vous le voyez, vous allez devoir trouver un autre moyen de faire ce que vous voulez.
Voici un exemple simple:
La sortie est:
Ce flacon chic n'est de créer un cache temporaire qu'il stocke sur la méthode, puis il utilise autre chose (le fait que le Flacon va enregistrer les classes à l'aide d'un
register
méthode de classe) réellement encapsule la méthode.Vous pouvez réutiliser ce modèle, cette fois à l'aide d'une métaclasse, de sorte que vous pouvez envelopper la méthode à l'importation de temps.
Sur la classe réelle (on pourrait faire la même à l'aide d'une métaclasse):
Source: https://github.com/apiguy/flask-classy/blob/master/flask_classy.py
Depuis python 3.6 vous pouvez utiliser
objet.__définissez_nom__
à faire cela de manière très simple. La doc stipule que__set_name__
est "appelé à l'époque la classe possédant propriétaire est créé".Voici un exemple:
Avis qu'il est appelé à la création de classes de temps:
Si vous voulez en savoir plus sur la façon dont les classes sont créées et en particulier exactement quand
__set_name__
est appelé, vous pouvez vous référer à la documentation sur la "Création de l'objet de classe".C'est une vieille question, mais il est venu à travers les vénusiens. http://venusian.readthedocs.org/en/latest/
Il semble avoir la capacité de décorer méthodes et de vous donner accès à la fois la classe et de la méthode pour le faire.
Note tht appel
setattr(ob, wrapped.__name__, decorated)
n'est pas typique de la façon de l'utilisation des vénusiens et un peu de défaites le but.De toute façon... l'exemple ci-dessous est complète et doit s'exécuter.
Vous aurez accès à la classe de l'objet sur lequel la méthode est appelée dans l'décorées méthode que votre décorateur doit retourner. Comme:
À l'aide de votre ModelA classe, ici est ce que cela fait:
Fonction ne sais pas si c'est une méthode à la définition du point, lorsque le décorateur code s'exécute. Seulement quand il est accessible via la classe/identificateur de l'instance, il peut connaître sa classe/instance. Pour surmonter cette limitation, vous pouvez décorer les descripteurs de l'objet de retarder réelle de décoration de code jusqu'à ce que l'accès/heure d'appel:
Cela vous permet de décorer individuels (statique|classe) méthodes:
Maintenant, vous pouvez utiliser le décorateur code de l'introspection...
...et pour le changement de comportement de la fonction:
</sigh>