Коротко о задаче
@python_quizРазберем этот квиз
Имеется фрагмент Python-кода с множественным наследованием. Нужно понять, какая реализация метода f() будет вызвана при создании экземпляра D и вызове D().f().
Исходный код

Что делает код
- A задаёт базовую реализацию f(), возвращающую 'A'.
- B наследует A, но не переопределяет f().
- C наследует A и переопределяет f(), возвращая 'C'.
- D наследует одновременно от B и C (в указанном порядке B, C).
При вызове D().f() интерпретатор ищет метод по порядку, определённому MRO (method resolution order).
Разбор MRO (порядка поиска методов)
Python использует алгоритм C3-линеаризации для вычисления MRO при множественном наследовании. Для данного класса D порядок будет такой:
- D
- B
- C
- A
Можно проверить это прямо в интерпретаторе:

Ожидаемый вывод:

Поэтому при поиске f() Python смотрит в D → B → C → A. В B метода f нет, в C есть — он и будет вызван.
Демонстрация результата

Анализ вариантов (куда бы могло вести заблуждение)
- "A": подошло бы, если бы C не переопределял f и ни в B, ни в C не было реализации отличной от A. Но здесь C содержит своё f(), и оно находится раньше A в поиске.
- "B": возможно подумать, что раз B стоит первым в списке базовых классов D(B, C), то выбор будет за B. Но B не определяет f(), поэтому поиск продолжается дальше — в C, где метод найден.
- "C": корректно — C содержит реализацию f(), и она обнаруживается при обходе MRO.
- "
TypeErrorиз-за конфликта MRO": возник бы при некорректной или неоднозначной иерархии наследования (например, если бы алгоритм C3 не смог построить допустимую линейную последовательность). В данном случае иерархия согласована, конфликтов нет.
Небольшой бонус — что если оба подкласса реализуют метод
Если и B, и C определят f(), то при D(B, C) будет выбрана реализация из B (левый приоритет):

Вывод
В рассматриваемом коде поиск метода следует порядку MRO D → B → C → A. Поскольку B не содержит f(), а C содержит, будет вызвана реализация из C и программа выведет строку 'C'.