# Python MRO **Python MRO** (Method Resolution Order) defines the order in which Python looks for a method or attribute in a class hierarchy. With multiple inheritance, determining which parent class's method to call requires a consistent, predictable algorithm—Python uses C3 linearization. Understanding MRO is essential for debugging multiple inheritance and knowing which method actually runs. ## Example This example shows MRO with multiple inheritance and how methods are resolved. ```python # run: python3 mro.py # description: method resolution order in multiple inheritance class A: def method(self): print("A.method") def a_only(self): print("A.a_only") class B(A): def method(self): print("B.method") def b_only(self): print("B.b_only") class C(A): def method(self): print("C.method") def c_only(self): print("C.c_only") class D(B, C): pass # Show MRO print("MRO for D:") for i, cls in enumerate(D.__mro__): print(f" {i}: {cls.__name__}") # Method resolution d = D() print("\nCalling methods:") d.method() # Uses B, not C d.a_only() # Inherited from A d.b_only() # Inherited from B d.c_only() # Inherited from C # Use super() to call parent method class E(B, C): def method(self): print("E.method") super().method() # Calls next in MRO print("\nWith super():") E().method() ``` ## Common patterns **C3 linearization algorithm**: - Preserves left-to-right order of parent classes - Respects parent class ordering - Ensures each class appears only once - Result: `Class → B → C → A → object` **Viewing MRO**: - `ClassName.__mro__`: tuple of classes in resolution order - `ClassName.mro()`: method returning list of classes - `help(ClassName)`: shows MRO in documentation **The `super()` function**: - Calls next method in MRO (not necessarily parent class) - `super().method()`: calls next class's method - Essential for cooperative multiple inheritance - Uses MRO to find what's "next" **Cooperative multiple inheritance** (best practice): - All classes call `super()` in the chain - Allows multiple inheritance to work smoothly - Each class should accept `**kwargs` to pass through unknown args - Results in diamond inheritance working correctly **Common mistakes**: - Assuming `super()` calls parent class (it actually calls next in MRO) - Not calling `super().__init__()` in subclass (skips parent initialization) - Mixing `super()` and direct parent calls (breaks MRO chain) **Diamond problem** (solved by C3): ``` A / \ B C \ / D ``` - D inherits from B and C, both inherit from A - C3 ensures A is called only once, at the end - MRO: D → B → C → A → object