Как перехватить вызовы метода экземпляра?

Я ищу способ перехвата вызовов метода экземпляра в классе MyWrapper ниже:

 class SomeClass1: def a1(self): self.internal_z() return "a1" def a2(self): return "a2" def internal_z(self): return "z" class SomeClass2(SomeClass1): pass class MyWrapper(SomeClass2): # def INTERCEPT_ALL_FUNCTION_CALLS(): # result = Call_Original_Function() # self.str += result # return result def __init__(self): self.str = '' def getFinalResult(self): return self.str x = MyWrapper() x.a1() x.a2() 

Я хочу перехватить все вызовы функций через мой класс-оболочку. В моем классе-оболочке я хочу отслеживать все строки результатов.

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

3 Solutions collect form web for “Как перехватить вызовы метода экземпляра?”

Какой-то быстрый и грязный код:

 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) 

Возможно, это не будет тщательным, но может быть достойной отправной точкой, я думаю.

То, что вы хотите сделать, очень похоже на этот вопрос . Вы должны взять свой пример кода в обратном порядке, я имею в виду создание класса для записи возвращаемых значений вызовов методов и создания классов, которые вы хотите посмотреть наследовать от него. Который дал бы что-то вроде этого

 class RetValWatcher(object): def __init__(self): self.retvals = [] def __getattribute__(self, name): attr = super(RetValWatcher, self).__getattribute__(name) if callable(attr): def wrapped(*args, **kwargs): retval = attr(*args, **kwargs) self.retvals.append(retval) return retval return wrapped else: return attr def getFinalRestult(self): return ''.join(self.retvals) class MyClass(RetValWatcher): def a(self): self.internal_z() return 'a1' def b(self): return 'b1' def internal_z(self): return 'z' x = MyClass() xa() xb() print x.getFinalResult() #'za1b1' 

С некоторыми незначительными изменениями этот метод также позволит вам записывать возвращаемые значения во всех экземплярах RetValWatcher.

Изменить: добавлены изменения, предложенные комментарием сингулярности

Edit2: забыл обработать случай, когда attr не является методом (снова синхронность thx)

Вы могли бы обернуть ваши методы с помощью декораторов как время instanciation:

 #!/usr/bin/env python import inspect def log(func): def _logged(*args, **kw): print "[LD] func", func.__name__, "called with:", args, kw result = func(*args, **kw) print "[LD] func", func.__name__, "returned:", result return result return _logged class A(object): def __init__(self): for x in inspect.getmembers(self, (inspect.ismethod)): if not x[0].startswith('__'): setattr(self, x[0], log(getattr(self, x[0]))) def hello(self): print "Hello" def bye(self): print "Bye" return 0 

Теперь, если вы вызываете hello или bye , вызов сначала проходит через log :

 a = A() a.hello() a.bye() # [LD] func hello called with: () {} # Hello # [LD] func hello returned: None # [LD] func bye called with: () {} # Bye # [LD] func bye returned: 0 
  • Что такое getattr () и как его использовать?
  • Как предотвратить hasattr от извлечения самого значения атрибута
  • Может ли использование `setattr` (и` getattr`) рассматриваться как плохая практика?
  • getattr для объектов класса
  • __getattr__ на модуле
  • Python: преобразовать строку в имя функции; getattr или равно?
  • Python - getattr и конкатенация
  • В чем разница между типом .__ getattribute__ и объектом .__ getattribute__?
  • Python - лучший язык программирования в мире.