简体   繁体   English

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

[英]How to declare decorator inside a class, to decorate an already decorated, inherited method?

I want to create a decorator which is a class member, and that is going to decorate an inherited method, which is decorated. 我想创建一个装饰器,它是一个类成员,它将装饰一个继承的方法,该方法被装饰。

example code: 示例代码:

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"

and

b = B()
b.inherited()

should output 应该输出

B.inherited was invoked B.inherited被调用

decorator was called! 装饰员被叫!


Having read this guide on decorators as class members , I still haven't been able to figure out how to decorate inherited methods with decorators defined in the super class. 阅读了有关装饰器作为类成员的指南之后 ,我仍然无法弄清楚如何使用超类中定义的装饰器装饰继承的方法。


Note, here @overrides is defined by the overrides package pip install overrides 注意,这里@overrides是由overrides 定义的pip install overrides @overrides


Also note i am currently using python 2.7, but would love both 2.7 and 3+ answers. 另请注意,我目前使用的是python 2.7,但同时喜欢2.7和3+的答案。

Thanks! 谢谢!

You were not that far! 你没那么远!

The key is that a decorator will receive one single argument which is the decorated function so it can only be a statmethod. 关键是装饰器将收到一个单独的参数,即装饰函数,因此它只能是statmethod。 And you also forgot that normal methods should be declared with a self argument. 而且您还忘记了常规方法应使用self变量声明。

But this code should work: 但是这段代码应该可以工作:

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"

I could test it under Python 2.7 except for the @overrides decorator (I commented it in my tests) 除了@overrides装饰器之外,我可以在Python 2.7下对其进行测试(我在测试中对此进行了评论)

Using Python 3, your code is just missing a few self arguments to be able to call the function with b.inherited() 使用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")

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

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