如何装饰父类并使子类使用它?蟒蛇

时间:2014-02-05 18:51:30

标签: python python-decorators

我想要的是创建一个类装饰器来装饰类并在子类上工作。

想象一下这个课程:

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 个答案:

答案 0 :(得分: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)

这对我有用!!如果我打错了,我会提前道歉。