При наследовании класс получает атрибуты и методы родителей и может их переопределить. Когда вызывается метод, Python ищет его по MRO (method resolution order) — линейному списку классов: сам класс, затем родители, в конце object.
При множественном наследовании MRO строится алгоритмом C3. Он гарантирует, что класс идёт раньше своих родителей, порядок родителей из объявления сохраняется, и каждый класс встречается один раз. Поэтому «ромб» (B и C наследуют A, D наследует B и C) не вызывает метод A дважды: MRO будет D, B, C, A, object.
super() возвращает объект, который ищет методы, начиная со следующего класса после текущего в MRO того объекта, для которого вызван метод. Поэтому в B.__init__ вызов super().__init__() при создании D пойдёт в C, а не сразу в A. Это позволяет строить «кооперативное» наследование: каждый класс вызывает super(), и вся цепочка отрабатывает по одному разу.
На практике множественное наследование используют для миксинов — небольших классов с одной добавкой поведения.