如何在类中声明装饰器,以装饰已经装饰的继承方法?

时间:2019-05-15 07:24:45

标签: python inheritance decorator

我想创建一个装饰器,它是一个类成员,并且将装饰一个继承的方法,该方法被装饰了。

示例代码:

class A(object):
    __metaclass__ = ABCMeta
    def __init__(self):
        pass

    @classmethod
    def the_decorator(cls, decorated):  # <-----this is what i want, with or without self/cls as an argument
        def decorator()
            #do stuff before
            decorated()
            print "decorator was called!"
            #do stuff after
        return decorator

    @abstractmethod
    def inherited():
        raise NotImplemented


class B(A):
    def __init__(self):
        super(B,self).__init__()

    #@A.the_decorator <--- this is what I want, 
    @overrides
    #@A.the_decorator <--- or this
    def inherited():
        print "B.inherited was invoked"

b = B()
b.inherited()

应输出

  

B.inherited被调用

     

装饰员被召唤了!


已经读过this guide on decorators as class members,但我仍然无法弄清楚如何用超类中定义的装饰器装饰继承的方法。


请注意,此处@overridesoverrides package pip install overrides

定义

还请注意,我目前正在使用python 2.7,但希望同时使用2.7和3+答案。

谢谢!

2 个答案:

答案 0 :(得分:2)

你还没那么远!

关键是装饰器将收到一个单独的参数,即装饰函数,因此只能是stat方法。而且您还忘记了应该使用self参数声明普通方法。

但是此代码应该可以工作:

class A(object):
    __metaclass__ = ABCMeta
    def __init__(self):
        pass

    @staticmethod
    def the_decorator(decorated):  # <-----this is what i want, with or without self/cls as an argument
        def decorator(self):
            #do stuff before
            decorated(self)
            print "decorator was called!"
            #do stuff after
        return decorator

    @abstractmethod
    def inherited():
        raise NotImplemented


class B(A):
    def __init__(self):
        super(B,self).__init__()

    @A.the_decorator #<--- this is what I want, 
    @overrides
    #@A.the_decorator <--- or this
    def inherited(self):
        print "B.inherited was invoked"

除了@overrides装饰器之外,我可以在Python 2.7下对其进行测试(我在测试中进行了评论)

答案 1 :(得分:0)

使用Python 3,您的代码仅缺少一些自变量即可使用b.inherited()调用函数

class A(object):
    __metaclass__ = ABCMeta
    def __init__(self):
        pass

    @classmethod
    def the_decorator(cls, decorated): 
        def decorator(*args, **kwargs):
            #do stuff before
            decorated(*args, **kwargs)
            print("decorator was called!")
            #do stuff after
        return decorator

    @abstractmethod
    def inherited(self):
        raise NotImplemented


class B(A):
    def __init__(self):
        super(B,self).__init__()

    @A.the_decorator
    @overrides
    def inherited(self):
        print("B.inherited was invoked")