0

Here are the few classes let's say, B, C, D and A, while in class A I am using super method which have class 'B' as an argument.

Where classes are as defined as below:

class B:
    def __init__(self):
        print('B')

class C:
    def __init__(self):
        print('C')

class D:
    def __init__(self):
        print('D')


class A(B,C,D):
    def __init__(self):
        super(B,self).__init__()

A()

When I am trying to initiate the class A, it should invoke class B as I passed B in super method. But it is giving me output 'C'. If I am passing D in super instead of B it's not giving any output. Why? Instead it just invoke class A and leave.

Why is this happening?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Akash Rathor
  • 109
  • 8
  • 2
    The first argument to super tells it which implementation to _skip_ and start after. So given the MRO (A -> B -> C -> D -> object) `super(B, self).__init__()` calls the implementation in C. See https://docs.python.org/3/library/functions.html#super: _"The search starts from the class right after the type."_ In Python 3, use the no-args form unless there's a really good reason not to. – jonrsharpe Jul 18 '22 at 13:47
  • Related: https://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance – jarmod Jul 18 '22 at 13:48
  • *All* the classes in the hierarchy need to use `super`, not just the child. `super` doesn't magically invoke multiple `__init__` methods; it just calls the *next* `__init__` method, which then has to use `super` itself to continue the chain of calls that will result in all the `__init__` methods being called in the correct order. – chepner Jul 18 '22 at 13:58

1 Answers1

2

The class you pass as an argument to super should be the current class whose superclass we want to look for, not the target superclass. With your class A, the method resolution order is

A < B < C < D < object

So super(A, self).__init__() would call the method on the class following A in the MRO, which is B. Likewise, super(B, self).__init__() would call the one following B, which is C. super(C, self) would give us D, and super(D, self) would give us object (Side note: I don't know what super(object, self) does, but it seems to return a proxy object that just eats all method calls).

What you're looking for is

super(A, self).__init__()

but since you're inside a method and want to call the next method in the MRO chain anyway (the default, and most sane, behavior), you can use the 0-argument form.

super().__init__()
Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • `super` is basically a type with special attribute lookup. The instance `super(A, self)` does little more than save a reference to `A` and `self`) (so that it can access `self.__mro__()`). When you ask for that instance's `__init__` attribute, you really get the `__init__` attribute of the first class in `self.__mro__()` following `A` that defines `__init__`. – chepner Jul 18 '22 at 14:01