Search code examples
pythoninheritanceoverridingsupermethod-resolution-order

Calling super().method() in a subclass that does not override method


The Python documentation of super states:

This is useful for accessing inherited methods that have been overridden in a class.

Is there a point in calling super().method() in a subclass that does not override method?

To me there is not, since calling self.method() would be equivalent, that is to say inheritance would look method up in self's superclasses using the same type(self).__mro__ method resolution order (given by the C3 linearization of self's superclass hierarchy) than super.

So to me, super is useful in this situation:

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

class B:
    pass

class C(B, A):
    def f(self):
        super().f()
        print("C")

C().f()  # prints A C

but not in this one:

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

class B:
    pass

class C(B, A):
    def g(self):
        super().f()  # should be just self.f()
        print("C")

C().g()  # prints A C

Solution

  • As noted by @chepner, calling super().method() in a subclass that does not override method is not equivalent to calling self.method(). The difference appears in subclasses of that subclass that override method.

    Compare:

    class A:
        def f(self):
            print("A")
    
    class B:
        pass
    
    class C(B, A):
        def g(self):
            super().f()  # == super(C, self).f(), so lookup starts after C in type(self).__mro__
            print("C")
    
    class D(C):    
        def f(self):
            print("D")
    
    D().g()  # prints A C, since D.__mro__ == (D, C, B, A, object)
    

    with:

    class A:
        def f(self):
            print("A")
    
    class B:
        pass
    
    class C(B, A):
        def g(self):
            self.f()  # lookup starts at the beginning in type(self).__mro__
            print("C")
    
    class D(C):
        def f(self):
            print("D")
    
    D().g()  # prints D C, since D.__mro__ == (D, C, B, A, object)