1
class Base():
def func(self):
    print("Base")


class A(Base):
    def func(self):
        print("A runs func")
        super().func()
        print("A func done")


class B(Base):
    def func(self):
        print("B runs func")
        super().func()
        print("B func done")

class C(A, B):
    def func(self):
        print("C runs func")
        super().func()
        print("C func done")


c = C()
c.func()

# get MRO
print(c.__class__.__mro__)

I'm trying to understand the super() in python, and I have this piece of code. When both class A and B have super(). everything is nice, I have this output
C runs func
A runs func
B runs func
Base
B func done
A func done
C func done
(<class 'main.C'>, <class 'main.A'>, <class 'main.B'>, <class 'main.Base'>, <class 'object'>)

=== but when A's super() commented out, I get
C runs func
A runs func
A func done
C func done

MRO info always printed, which is fine

=== when only B's super() commented out, I get
C runs func
A runs func
B runs func
B func done
A func done
C func done

=== when both super() are gone, it's same as no super() in A. Is this happening because python only traces according to the MRO table, and stops where there's no super()? but print(c.class.mro) shows every class is executed. Why is it the class gets "executed" but func() is not executed?

PopCornnnn
  • 11
  • 2
  • Isn't it clear? You saw yourself that the MRO is __C -> A -> B -> Base -> object__, so if you comment out super at A then you're breaking the chain there. The outputs all looks correct, I don't see any surprises there. – wim Jan 28 '23 at 16:49
  • Python is never going to call any class's `func()` method on its own. How could it, what parameters would it use? (Keep in mind that you're under no obligation to use the same parameter list for overridden methods, as you've done here!). Every call is the direct result of you making a call - the only thing `super()` adds is that you don't have to explicitly name the class being called each time. – jasonharper Jan 28 '23 at 16:50
  • I feel like I'm missing something basic. Why does B's `func()` even execute at all? Both of C's parent classes have `func()`, so I would have expected the super call in c to find `A.func` and stop looking. Why does it continue on to also find `B.func`? – John Gordon Jan 28 '23 at 16:56
  • @JohnGordon Because `A.func` _also_ calls to super, and the next in line in the MRO is `B` – wim Jan 28 '23 at 17:14
  • @wim But A's super is Base, surely? Why would A's super find B? – John Gordon Jan 28 '23 at 17:19
  • @wim Are you saying that A.super "remembers" that it was originally called from C? – John Gordon Jan 28 '23 at 17:25
  • I am becoming increasingly convinced that multi-inheritance is simply a Bad Idea. – CrazyChucky Jan 28 '23 at 17:57
  • 1
    @JohnGordon Yes. That's precisely the role of super (to remember the next method, which is not always the parent class but sometimes a sibling class like in this example). Super is a misnomer imo, because it sounds as though it refers to parent class. In the [programming language from which Python copied its MRO implementation](https://opendylan.org/) super is named "next-method", a less misleading name. – wim Jan 28 '23 at 19:01
  • 1
    Possible duplicate: [Confused in Understanding the flow of execution in Python Classes](https://stackoverflow.com/q/70981594/674039) – wim Jan 28 '23 at 19:04
  • thank you, I understand it now. I think the reason why I find this strange is I tried to understand this in the Java way... – PopCornnnn Jan 28 '23 at 20:22

0 Answers0