繁体   English   中英

在基类和派生类中使用基类的装饰器

[英]Using decorator from base class both in base class and derived class

我有一些带有某些方法的python对象,在这些方法中,我希望在开始时进行一些检查,根据此检查,方法的代码将运行,或者将引发执行。 我不希望在做装饰器时在每个方法的开头都复制“检查”代码,我还希望将装饰器嵌入到类本身中,因为它与之密切相关。 所以基本上:

代替这个

class A(object):

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

我想要这个

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类派生一个类并执行相同的装饰器检查时,就会遇到问题。 再一次,我不想复制代码,所以我想重用基类A中的装饰器,以在派生类中执行检查。 我读过有关将装饰器转换为@classmethod但是当我这样做时,我可以在派生类中使用装饰器,而不再在基类中使用装饰器!

所以基本上我想要这样的事情:

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 classmethod ,而不是classmethod ,并要求以一种稍微不寻常的方式使用它,但仅使用。

有关使用这样的装饰器的必要性的更多信息,请参阅我的问题在类主体中调用类staticmethod?

class A(object):
    @staticmethod
    def decorator(function):
        def function_wrapper(*args, **kwargs):
            print('in function_wrapper')
            return function(*args, **kwargs)
        return function_wrapper

    @decorator.__func__  #### Note unusual decorator usage inside defining class
    def a_method(self):
        print('in a_method')

class B(A):
    @A.decorator  #### Normal decorator usage outside defining class
    def b_method(self):
        print('in b_method')

避免使用__func__并将其保留在第一类中的一种方法是将其转换为staticmethod直到类定义的最后:

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__另一种方法是这样的:

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

这具有使装饰器的使用非常均匀的附加优点。

我的第一个问题是,我要这样做吗?

正如martineau在下面说的那样,好的做法是将经典装饰器放在课外。

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)

经典装饰器在类创建期间被调用,该创建时间比创建实例早。 参考

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM