2011-01-18 20 views
9

aşağıda sınıfta MyWrapper yılında örnek yöntemi çağrıları önünü bir yol arıyorum: Bütün işlev çağrıları benim sarıcı sınıfı aracılığıyla yapmak yolunu kesmek isteyenÖrnek yöntem çağrıları nasıl engellenir?

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() 

. Sarıcı sınıfımda, tüm sonuç dizelerini takip etmek istiyorum.

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

cevap

6

Bazı hızlı ve kirli kodu:

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) 

kapsamlı olmasa gerek, ama iyi bir başlangıç ​​noktası olabilir sanırım.

+0

Çok teşekkürler durumda işlemek için unuttum! İstediğim kadar harika çalışıyor! :-) –

+1

Bilmeniz güzel - rica ederim. Lütfen cevabı "kabul edilen" olarak etiketledikten sonra :) – Shadikka

2

Sen dekoratörler ile instanciation zaman yöntemlerinizi sarabilirdiniz:

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 
2

Ne yapmak istediğim: Artık hello veya bye ararsanız

#!/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 

, çağrı ilk log geçer this question'a oldukça benzer. Örnek kodunuzu ters sırayla almalısınız, yani yöntem çağrılarının geri dönüş değerlerini kaydetmek için bir sınıf oluşturmak ve izlemek istediğiniz sınıfları ondan çıkarmak. bazı küçük değişikliklerle birlikte bu

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() 
x.a() 
x.b() 
print x.getFinalResult() 
#'za1b1' 

gibi bir şey verecekti hangisi, bu yöntem, aynı zamanda tüm RetValWatcher örneği arasında dönüş değerlerini kaydetme olanağı sağlayacaktır.

Düzenleme: tekillik comment

Edit2 önerdiği eklenen değişiklikler: attr (yine thx tekillik) bir yöntem olmadığı durumlarda

+0

+1, bu yöntemi daha çok beğeniyorum, ama bazı sözlerim var: 1) 'retvals = [] 'i ile" self.retvals = [] ', 2) değiştirin OP x.getFinalResult() 'nin durumu __za1a2__ __a1a2__ döndürecektir, 3) 'insert.ismethod' veya' callable (attr) 'yerine 'hasattr (attr,' __call __ ')' kullanmak daha iyidir. – mouad

+0

eksik 'kendini' sadece bir gözetimdi, ama diğer 2 puan için haklısınız. edited;) – MatToufoutu

+0

Ahh tekrar özür dilerim; 'ununu unutursun: eğer' eğer '(' attn 'ise)' 'attr' değerini döndürür: 'çünkü özellik aramayı gizlemek istemezsiniz :) – mouad

İlgili konular