1

I came across a class inheritance problem in python.

class A:
    def foo(self):
        print("A")

class B(A):
    def foo(self):
        print("!B")
        super(B,self).foo()
        print("B")

class C:
    def foo(self):
        print("!C")
        super(C,self).foo()
        print("C")


class D(C,B):
    def foo(self):
        print("!D")
        super(D,self).foo()
        print("D")

bar = D().foo()

Why the output is

!D
!C
!B
A
B
C
D

Is it because class C gets a parent class from class D's inheritance?

Wai
  • 13
  • 2

1 Answers1

0

Despite it's name, super() is not calling on "the" parent class (which makes no sense since with multiple inheritance you can have more than one single parent class...) but on the next class in the __mro__.

In you case, the mro for D is C, B, A, so D.foo will call C.foo which will call B.foo which will call A.foo.

If what puzzles you is that super(C, self).foo resolves to B.foo even while C doesn't inherit from B, you have to remember that super will use the mro of self, which in this case DOES include B since self here is a D instance, not a C instance. That's actually whysuper needs both the current class and the current instance FWIW.

Is it because class C gets a parent class from class D's inheritance?

Almost... that's not how it works (cf above), but the effective result is quite similar.

I was expecting super(C,self).foo() will throw exception

It will if the class super() resolves too has no foo method (or if it has a non-callable foo attribute):

class E(C):
    def foo(self):
        print("!E")
        super(E,self).foo()
        print("E")

E().foo()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "sup.py", line 65, in foo
    super(E,self).foo()
  File "sup.py", line 50, in foo
    super(C,self).foo()
AttributeError: 'super' object has no attribute 'foo'

And this comes from the super(C, self).foo() call in C - in this case, the next class in E.__mro__ is object, which doesn't indeed define a foo method ;-)

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118