In common case, super() takes two arguments: a class and an instance of that class. (1) The instance object (self) determines which MRO will be used to resolve any attributes. (2) The provided class determines a subset of that MRO, because super() only uses those entries in the MRO that occur after the class provided.
Thus in above case when super inside B is called from instance of D Object the self refer to D object (ie instance object) and mro of D (ie instance object) is [D,B,C,A] therefore according to (2) only those entries in MRO which occur after B will be used. ie [C,A]
Thus the recommended usage is to provide the class where super() was used as the first argument, and the standard self as the second argument. The resulting object will retain the instance namespace dictionary of self, but it only retrieves attributes that were defined on the classes found later in the MRO than the class provided.
Hence if we redefine B as
class B(A):
def test(self):
return 'B->'+super(C, self).test()
then calling D().test() will output ==> 'B->A' explanation: from (1) above MRO of self == [D,B,C,A,object] from (2) above only those entries of MRO will be used which occur after provided class (ie C) hence super will call test method of A.