Consider the following class hierarchy
import inspect
class A(object):
def func(self):
return "A.func"
class B(A):
def func(self):
return "B.func"
class C(A):
def func(self):
return "C.func"
class D(B, C):
def func(self):
return "D.func"
class E(D):
def func(self):
return "E.func"
if __name__ == "__main__":
def printmro(k):
print "mro({0}): {1}".format(k.__name__,
", ".join(klass.__name__ for klass in inspect.getmro(k)))
for k in (A,B,C,D,E):
printmro(k)
x = E()
print "type(x):", type(x).__name__
print "x.func():", x.func()
print "super(D, x).func():", super(D, x).func()
""" my output-->
mro(A): A, object
mro(B): B, A, object
mro(C): C, A, object
mro(D): D, B, C, A, object
mro(E): E, D, B, C, A, object
type(x): E
x.func(): E.func
super(D, x).func(): B.func
""" Themro of a type is the 'method resolution order'. It means that when looking for the method x.func, since x is a E instance, the interpreter looks for a method func() in each of the classes E, D, B, C, A, object in this order, because this is class E's mro.
Now, since x is also an instance of D, we can write super(D, x).func(). Then the method will be searched in D's mro without the class D itself. Since D's mro is D, B, C, A, object, python looks in the list of classes B, C, A, object, and it finds B.func().
In python 2, super is not very useful because one must explicitely use a reference to the class (Application in your example). In python 3, you can use super() in a method without the class name and this improves maintenability because the class name can be changed without modifying the code.