2014-02-05 28 views
3

我想要的是創建一個類裝飾器來裝飾一個類,並在子類上工作。如何裝飾父類並讓子類使用它? python

想象一下這個類:

class CustomBaseTest(TransactionTestCase): 
    def __init__(self, *args, **kwargs): 
     ... 

    def more_custom_helpers(self): 
     ... 

和真正的考驗:

class FooTest(CustomBaseTest): 
    def decorate_this_foo_is_ok(self): 
     .... 

    def decorate_this_fails(self): 
     ... 

我要的是用一個裝飾在CustomBaseTest該發現與「decoratte_this_」和執行自定義啓動所有的方法代碼之前和之後。我已經有裝飾者​​,像這樣:

def class_decorator(klass): 
    is_method_test = lambda m: not m.startswith('_') and m.startswith('decorate_this_') and isinstance(getattr(klass, m), MethodType) 
    test_methods = filter(is_method_test, dir(klass)) 

    for method_name in test_methods: 
     class_method = getattr(klass, method_name) 

     def helper(mname, method): 
      @wraps(method) 
      ... some logic here 
      retval = method(*a, **kw) 
      ... more logic here 
      return retval 
     return wrapper 

     fn = MethodType(helper(method_name, class_method), None, klass) 
     setattr(klass, method_name, fn) 
    return klass 

你知道如果有可能做到這一點嗎?如何?

謝謝!!!

+1

1)嘗試設置類的'__metaclass__'屬性。 2)修改基類的'__new__'方法。 –

+2

類裝飾只適用於他們裝飾的實際類。正如Joel Cornett所說,你可以使用元類。谷歌圍繞如何使用元類的信息。 – BrenBarn

+0

__metaclass__是要走的路!多謝你們!!!我解決了我的問題! :) – pahko

回答

1

感謝@Markku和@BrenBarn。

以下是解決方案。

首先我們有一個簡單的裝飾:

from functools import wraps 
def my_decorator(func): 
    @wraps(func) 
    def wrapper(*args, **kwargs): 
     # do some stuff 
     retval = func(*args, **kwargs) 
     # do more stuff 
     return retval 
    return wrapper 

和元類:

class ProfileMetaByClass(type): 
    def __init__(cls, name, bases, dct): 
     for method_name, method in dct.items(): 
      if method_name.startswith('decorate_this_'): 
       setattr(cls, key, my_decorator(value)) 
     type.__init__(cls, name, bases, dct) 

併爲我工作!如果我犯了一個錯字,我會提前道歉。