← Back to Python

MRO, super(), Diamond Problem

PythonSeniorpython

The Question

Explain Python's MRO, how super() works, and the diamond problem.

What a Strong Answer Covers

  • C3 linearization
  • "super() follows MRO
  • "base called once

Senior-Level Answer

Python's Method Resolution Order (MRO) determines which class's method is called when a name is looked up in an inheritance hierarchy. For single inheritance, this is trivial. For multiple inheritance, Python uses C3 linearization, an algorithm that produces a consistent, predictable linear ordering of all classes in the hierarchy.

The diamond problem is the motivating case: class D inherits from B and C, both of which inherit from A. If D calls a method defined in A, which path wins — D→B→A or D→C→A? Worse, if B and C both override the method, which override runs? Without a defined resolution order, the answer is ambiguous and depends on implementation.

C3 linearization produces an MRO that satisfies three properties: the class itself comes first; a class always appears before its parents; if multiple bases are specified, their relative order from the class definition is preserved. For the diamond D(B, C), D's MRO is [D, B, C, A, object]. You can inspect this at runtime with `ClassName.__mro__` or `ClassName.mro()`.

`super()` is the mechanism for traversing the MRO cooperatively. Crucially, `super()` does not mean 'call the parent class' — it means 'call the next class in the MRO of the original instance's class.' This distinction matters: when B calls `super().__init__()` inside `D.__init__()`, super() resolves to C (the next in D's MRO), not to A. If each class in the chain calls `super()`, all `__init__` methods run exactly once, in MRO order, without A being initialized twice.

This is cooperative multiple inheritance. It only works correctly when all classes in the hierarchy use `super()` consistently. Mixing `super()` calls with explicit parent calls (like `A.__init__(self)`) breaks the cooperation and can cause A to be called twice or skipped.

A practical implication: `super()` in Python 3 is zero-argument and uses `__class__` cell references — you no longer need to pass the class name explicitly as in Python 2. `super()` == `super(__class__, self)`.

When multiple inheritance is genuinely needed, mixins are the typical pattern: small, focused classes that add one capability and always use `super()`, designed to be composed into a target class without direct instantiation.

What Separates a 2/3 from a 3/3

2/3 — Passing but Incomplete

Correctly explains the diamond problem, describes C3 linearization at a conceptual level, and explains that super() follows MRO rather than just calling the immediate parent.

3/3 — Strong Answer

All of the above plus: walks through the concrete MRO for a diamond hierarchy, explains cooperative multiple inheritance (all classes must use super()), describes what breaks when they don't, and mentions the mixin pattern.

Common Mistakes

  • Saying super() calls 'the parent class' — this is only correct for single inheritance. In multiple inheritance, super() calls the next class in the MRO, which may not be an immediate parent.
  • Not knowing that C3 linearization is the algorithm — candidates often describe MRO correctly without knowing the mechanism's name or properties.
  • Missing the cooperative requirement — describing super() correctly but not explaining that all classes in the chain must use it for cooperative MI to work.
  • Confusing MRO with method overriding — MRO determines lookup order, but overriding is about which method definition is used at a given position in the chain.

Follow-Up Questions

  • What is the MRO for class D(B, C) where B(A) and C(A) and A(object)? — D → B → C → A → object. Walk through C3: D first, then merge [B,A,object], [C,A,object], [B,C]. B is a valid head (not in any tail), take B, etc.
  • What happens if you mix super() calls with explicit parent calls in cooperative MI? — The explicit call bypasses the MRO, causing some __init__ methods to run twice (if they're called both via super() chain and explicitly) or not at all.
  • When does Python raise a TypeError about MRO inconsistency? — When a class definition would produce an MRO that violates C3's monotonicity constraint — e.g., class C(A, B) where elsewhere B inherits from A, reversing their expected order.
  • How do mixins use MRO, and why is super() essential in a mixin? — Mixins sit in the MRO between the target class and the rest. Without super(), the mixin breaks the chain and methods below it in the MRO never run.

Related Questions

  • GIL — What It Is and What It Protects
  • ThreadPoolExecutor & ProcessPoolExecutor
  • Decorators — Under the Hood
  • Generators & yield
  • Context Managers

Can You Explain This Cold?

Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.

Get Graded — Free Assessment
GrindQuestionsAITechnical interview assessment
TermsPrivacyAbout