0

I have two parent classes I cannot redefine (say, A and B), with methods I need to overload using the exact same way (so as to obtain, say, BetterA and BetterB). I could duplicate the code for both classes, but I am not satisfied with that. In Python 3.6, I thought I can get rid of this using multi inheritance and a provider class. This is what I obtained so far:

# here are the initial classes I cannot edit
class A:
    def __init__(self, a=0):
        self.a = a

class B:
    def __init__(self, b=0):
        self.b = b

# here is the provider class
class Provider:
    def __init__(self, c, *args, **kwargs):
        self.c = c

        # more code here

        self.init_child(*args, **kwargs)

# here are the new classes
class BetterA(Provider, A):
    def init_child(self, *args, **kwargs):
        A.__init__(*args, **kwargs)

class BetterB(Provider, B):
    def init_child(self, *args, **kwargs):
        B.__init__(*args, **kwargs)

if __name__ == '__main__':
    a = BetterA(8, a=10)
    b = BetterB(10, b=8)

This works, but it is not very graceful… Especially, if I want to override more methods (always, in the same way), I have to recall them in BetterA and BetterB.

If there a better way to achieve what I want?

1 Answer 1

2

super() works with multiple inheritance:

# here is the provider class
class Provider:
    def __init__(self, c, *args, **kwargs):
        self.c = c

        # more code here

        super().__init__(*args, **kwargs)

# here are the new classes
class BetterA(Provider, A):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

class BetterB(Provider, B):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

if __name__ == '__main__':
    a = BetterA(8, a=10)
    b = BetterB(10, b=8)

and you don’t need to redefine Better*.__init__ if it’s not doing anything beyond calling the super method:

# here are the new classes
class BetterA(Provider, A):
    pass

class BetterB(Provider, B):
    pass

Another option you might prefer depending on whether you need to implement any more functionality in the Better* types is a function to create a class:

def provided(cls):
    class Provided(cls):
        def __init__(self, c, *args, **kwargs):
            self.c = c

            # more code here

            super().__init__(*args, **kwargs)

    return Provided


BetterA = provided(A)
BetterB = provided(B)
Sign up to request clarification or add additional context in comments.

2 Comments

Wow! I would say this is a "super" solution! But I'm wondering: which init the super at line 8 (first code block) is calling and how?
@Neraste: It’s calling A.__init__ or B.__init__ according to BetterA.__mro__ or BetterB.__mro__.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.