Search code examples
pythonclassinheritancepython-decorators

Auto inherite a parent class with decorator


I have a class decorator p() that can be used only on classes that inherite from some abstract class P.

So anytime someone uses p it should be written as follows:

@p()
class Child(P):
    ...

Is there any way to automatically inherite P using the decorator p() so it would simply be written as follows:

@p()
class Child:
    ...

Solution

  • As I commented, it's tricky to apply a base class using a decorator the way you asked. However, it is a lot easier if you try an alternative approach, where the decorator's behavior is incorporated into the base class, rather than the other way around.

    Here's an example, that prints out a message before calling the child class's __init__ method:

    from functools import wraps
    
    class Base:
        def __init_subclass__(cls):
            original_init = cls.__init__
    
            @wraps(cls.__init__)
            def wrapper(self, *args):
                print("foo")
                original_init(self, *args)
    
            cls.__init__ = wrapper
    
    
    class Derived(Base):
        def __init__(self):
            print("bar")
    

    You can customize the wrapper function's behavior to do whatever your decorator currently does (rather than just printing a message). And of course, the base class can have whatever other behavior you want the derived class to inherit, rather than just the __init_subclass__ machinery that enables changing the subclass's __init__ method.