关于python:在基类和派生类中使用基类的装饰器

Using decorator from base class both in base class and derived class

我有一些带有一些方法的Python对象,我希望在begging时进行一些检查,根据这种检查,方法的代码将运行,或者引发一个执行。我不想在每个方法的开头复制"check"代码,而是希望将decorator嵌入类本身,因为它与类密切相关。所以基本上:

而不是这个

1
2
3
4
5
6
7
class A(object):

    def a_method(self):
        if self.check_var is True:
            (some_code)
        else:
            raise Exception

我想要这个

1
2
3
4
5
6
7
8
9
10
11
12
13
class A(object):

    def decorator(function):
        def function_wrapper(self, *args, **kwargs):
            if self.check_var is True:
                return function(self, *args, **kwargs)
            else:
                raise Exception
        return function_wrapper

    @decorator
    def a_method(self):
        (some_code)

我的第一个问题是,我这样做对吗?或者有更好的方法。我有许多类的方法需要进行这种检查,所以我不想不必要地复制代码。

我的第二个问题是,如果按照我描述的方式来做,当我想从类A派生一个类并执行相同的装饰器检查时,会遇到一个问题。同样,我不想复制代码,所以我想重用基类A中的修饰符来在派生类中执行检查。我读过将decorator转换成@classmethod的文章,但是当我这样做的时候,我可以在派生类中使用decorator,而不再在基类中使用!

所以基本上我想要这样的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A(object):

    @classmethod #maybe
    def decorator(function):
        def function_wrapper(self, *args, **kwargs):
            if self.check_var is True:
                return function(self, *args, **kwargs)
            else:
                raise Exception
        return function_wrapper

    @decorator
    def a_method(self):
        (some_code)

class B(A):

    @decorator
    def b_method(self):
        (some_code)

有人知道怎么做吗?


既然你愿意把装饰放在教室里(如我所建议的那样,把装饰放在教室外面),那么下面就有了一个做装饰的方法。它使装饰成为一种staticmethod的方法,并要求它在一个很小的不寻常的方式,但只有在课堂上。

关于使用装饰类的需要的更多信息,请参看我的问题叫&NBSP&StaticMethod&NBSP&Within&NBSP&NBSP?

ZZU1

一种避免使用__func__的方法是,在第一类中保留定义,然后将其转化为staticmethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A(object):
    def decorator(function):
        def function_wrapper(*args, **kwargs):
            print('in function_wrapper')
            return function(*args, **kwargs)
        return function_wrapper

    @decorator
    def a_method(self):
        print('in a_method')

    decorator = staticmethod(decorator)  #### convert for use outside this class

class B(A):
    @A.decorator
    def b_method(self):
        print('in b_method')

然而,另一种避免__func__的方法是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A(object):
    class Check:
        @staticmethod
        def decorator(function):
            def function_wrapper(*args, **kwargs):
                print('in function_wrapper')
                return function(*args, **kwargs)
            return function_wrapper

    @Check.decorator
    def a_method(self):
        print('in a_method')

class B(A):
    Check = A.Check

    @Check.decorator
    def b_method(self):
        print('in b_method')

这对装饰的使用具有额外的优势。


My first question is, am I going about this right?

马丁内乌在下面说,好的做法是把经典的装饰课放在外面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def get_decorator(function, argument):
    def function_wrapper(*args, **kwargs):
        if argument is True:
            return function(*args, **kwargs)
        else:
            raise Exception
    return function_wrapper

class A(object):
    def __init__(self):
        self.check_var = True
        self.a_method = get_decorator(self.a_method, self.check_var)
    def a_method(self):
        (whatever)

class B(A):
    def __init__(self):
        super(B, self).__init__()
        self.b_method = get_decorator(self.b_method, self.check_var)
    def b_method(self):
        (whatever)

BLCK1/