将超类中的方法用作子类的“装饰器”

时间:2019-12-03 11:51:22

标签: python python-3.x inheritance

我有一种情况,我想在python的子类中“标记”方法,基本上说“将这个子类方法包装在超类的方法内”

例如:

class SuperClass:
    ...
    def wrapping_method(func):
        # do something in the SuperClass instance before the method call
        func(args)
        # do something in the SuperClass instance after the method call
    ...

class SubClass(SuperClass):
    ...
    def my_function(args):
        # do something in the SubClass instance
    ...

我想要这样,以便每当我在SubClass中调用my_function(args)时,都将使用作为参数传递的方法wrapping_method()(与所有{{ 1}}参数)。

我不熟悉如何在这里使用装饰器之类的东西,但我希望能够使用某种类似注解的“ @”符号来标记子类方法。

1 个答案:

答案 0 :(得分:1)

使用装饰器和子类是正交的。您可以在基类方法(或您喜欢的任何位置)中定义装饰器,并将其应用于子类方法(或您喜欢的任何位置)。

class SuperClass:
    """Type that counts invocation of methods decorated with @counted"""
    def __init__(self):
        self.count = 0

    # define decorator by taking one callable as argument
    @staticmethod
    def counted(method):  # 1
        """Decorate a method to count its invocations"""
        def counted_method(self, *args, **kwargs):
            self.count += 1
            bound_method = method.__get__(type(self), self)  # 2
            return bound_method(*args, **kwargs)
        return counted_method

class SubClass(SuperClass):
    # use `@decorator` to decorate a method
    @SuperClass.counted
    def my_method(self):
        print("doing something in the SubClass instance")

这里,counted是常规修饰符,这意味着它只需要一些可调用(#1)并对其执行 some 操作-在此示例中,将其包装。由于counted_method包围了实际的方法,因此我们必须manually invoke the descriptor protocol#2)来模拟方法查找。

>>> instance = SubClass()
>>> instance.count
0
>>> instance.my_method()
doing something in the SubClass instance
>>> instance.count
1