12
votes

Comment intercepter les appels de méthode d'instance?

Je cherche un moyen d'intercepter les appels de méthode d'instance dans la classe MyWrapper code> ci-dessous: xxx pré>

Je veux intercepter tous les appels de fonction faire via ma classe d'emballage. Dans ma classe wrapper, je veux garder une trace de toutes les chaînes de résultat. P>

result = x.getFinalResult()
print result == 'a1a2'


0 commentaires

3 Réponses :


7
votes

Un code rapide et sale:

class Wrapper:
    def __init__(self, obj):
        self.obj = obj
        self.callable_results = []

    def __getattr__(self, attr):
        print("Getting {0}.{1}".format(type(self.obj).__name__, attr))
        ret = getattr(self.obj, attr)
        if hasattr(ret, "__call__"):
            return self.FunctionWrapper(self, ret)
        return ret

    class FunctionWrapper:
        def __init__(self, parent, callable):
            self.parent = parent
            self.callable = callable

        def __call__(self, *args, **kwargs):
            print("Calling {0}.{1}".format(
                  type(self.parent.obj).__name__, self.callable.__name__))
            ret = self.callable(*args, **kwargs)
            self.parent.callable_results.append(ret)
            return ret

class A:
    def __init__(self, val): self.val = val
    def getval(self): return self.val

w = Wrapper(A(10))
print(w.val)
w.getval()
print(w.callable_results)


1 commentaires

Bon à savoir - de votre choix. Veuillez étiqueter la réponse comme "acceptée" alors :)



2
votes

Vous pouvez envelopper vos méthodes avec des décorateurs un temps d'instanciation: xxx

maintenant si vous appelez bonjour ou au revoir , l'appel va via journal d'abord: xxx


0 commentaires

2
votes

Ce que vous voulez faire est assez similaire à Cette question . Vous devez prendre votre exemple de code dans l'ordre inverse, je veux dire créer une classe pour enregistrer des valeurs de retour d'appels de méthode et rendre les classes que vous souhaitez regarder hériter de celui-ci. Qui donnerait quelque chose comme ça xxx

avec quelques modifications mineures, cette méthode vous permettrait également d'enregistrer des valeurs de retour sur toutes les instances ReValWatcher.

Edit: Ajouté Modifications suggérées par le commentaire de la singularité

EDIT2: oublié de gérer le cas où ATTR n'est pas une méthode (THX SINGULARITY)

Edit3: Typo fixe


4 commentaires

+1, j'aime cette méthode davantage, mais j'ai quelques remarques: 1) Remplacez Reveal = [] avec auto.revals = [] , 2) dans le cas de Le OP x.getFinalResult () retournera za1a2 pas a1a2 , 3) Je pense qu'il est préférable d'utiliser inspect.ismethod ou appelable (attr) au lieu de hasattr (attr, __call __ ') .


Le «Self» manquant était juste une surveillance, mais vous avez raison pour les 2 autres points. édité;)


Ahh désolé encore; Vous oubliez else: retour attr pour le si appelable (attr): parce que vous ne voulez pas obscurer l'appel d'attributs :)


TYPO: def getFinalrestTultTult (auto):