-3

I have two classes, with the same parameter initialized by their __init__ method. I would like to inherit both classes in class "X". But I will get: TypeError: B.__init__() missing 1 required positional argument: 'my_param'

Reproducible Example:

class A:
    def __init__(self, my_param):
        super().__init__()
        self.my_param = my_param


class B:
    def __init__(self, my_param):
        super().__init__()
        self.my_param = my_param * 2


class X(A, B):
    def __init__(self, my_param):
        super().__init__(my_param=my_param)

a = X(my_param=1)
print(a.my_param)

A and B are Mixins, they provide additional functionality for Child Classes. They can be used separetly or together. Lets's say class A provides searhc functionality for search by ID, where class B provides search by value.

Is there a way to set my_param for each of A and B or to set it without getting the error?

Andreas
  • 8,694
  • 3
  • 14
  • 38

2 Answers2

6

This can't be done just using super() calls, because the superclass of the last class in the chain will be object, which doesn't take a my_param parameter.

See python multiple inheritance passing arguments to constructors using super for more discussion of parameter passing to __init__() methods with multiple inheritance.

So you need to change X to call the superclass init methods explicitly, rather than using super(). And A and B shouldn't call super().__init__() because they're subclasses of object, which doesn't do anything in its __init__().

class A:
    def __init__(self, my_param):
        self.my_param = my_param

class B:
    def __init__(self, my_param):
        self.my_param = my_param * 2

class X(A, B):
    def __init__(self, my_param):
        A.__init__(self, my_param=my_param)
        B.__init__(self, my_param=my_param)
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thank you for your answer!, Unfortunately when I try this, I get the error: ´TypeError: object.__init__() takes exactly one argument (the instance to initialize)` I – Andreas Aug 26 '22 at 21:53
  • ahhh, thank you so much for the explanation! I tried to solve it in the meantime by creating an abstract class shared by A and B but it feels not really clean, I definetly can use your solution and learned something new on the way, thank you again. – Andreas Aug 26 '22 at 22:09
1

Since A and B share the same fields, I think it makes sense to make one inherit from the other - in this case, B inherit from A. That way, you'll only need to subclass from B in class X.

For example:

class A:
    def __init__(self, my_param):
        self.my_param = my_param


class B(A):
    def __init__(self, my_param):
        super().__init__(my_param * 2)
        # or:
        #   A.__init__(self, my_param * 2)


class X(B):
    def __init__(self, my_param):
        super().__init__(my_param=my_param)


a = X(my_param=1)
print(a.my_param)  # 2
rv.kvetch
  • 9,940
  • 3
  • 24
  • 53
  • 2
    This class hierarchy may not make sense for the rest of the behavior of B. – Barmar Aug 26 '22 at 15:10
  • Totally right, I did make an assumption that since B and A share the same field, it might make sense to introduce some sort of inheritance. But I agree that this might not be the best idea, depending on the use case or scenario. – rv.kvetch Aug 26 '22 at 15:12
  • 1
    @rv.kvetch thank you for your answer, class A and B are Mixins, they provided different functunalities e.g. search by value (A) and search by id (B). Some childs of A and B only need A as parent, some only B and some both. But both classes share some attributes. – Andreas Aug 26 '22 at 21:55