简体   繁体   中英

Use method from superclass as "decorator" for subclass

I have a scenario where I want to "mark" methods in a subclass in python to basically say "wrap this subclass method inside a method in the superclass"

For example:

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
    ...

I want it so that whenever I call my_function(args) in SubClass, the wrapping_method() in SuperClass is called instead with the method my_function passed in as an argument (with all of the my_function arguments somehow).

I am unfamiliar with how things like decorators can be used here but I would like to be able to use some kind of annotation-like '@' notation to 'mark' subclass methods.

Using decorators and subclassing is orthogonal. You can define a decorator in a base class method (or anywhere you like) and apply it to a sub class method (or anywhere you like).

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

Here, counted is a regular decorator, meaning it just takes some callable ( #1 ) and performs some operation on it -- in this example, wrapping it. Since the counted_method wraps around the actual method, we must manually invoke the descriptor protocol ( #2 ) to emulate method lookup.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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