According to the official documentation about Python classes, we see in the multiple inheritance section the definition:
For most purposes, in the simplest cases, you can think of the search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy.
That is, using your example, if a method / attribute is not found in the D
class, Python will search by its definition in the C
class, first left. If it did not find it, it would go deeper, for the base classes of C
. As it does not have, it returns to class B
and, if it does not, it goes to class A
, if it does not, for the base classes of A
. If you still can not find the definition, throw the exception.
Therefore, when running var.y()
, the definition of y
in D, C, B, A
, in this order is searched. It finds in C
, so it returns C.y
. When executed var.get_c()
, the same thing is also found in C
, returning the value of self.c
, but what happens here is that in the initializer of class D
, you execute the initialization of class B
after% of class C
and in both the self.c
property is set. That is, when executed C.__init__()
, the value of self.c
will be 5, but when executed B.__init__()
, the value of self.c
becomes 16, which explains why var.get_c()
returns the value 16-