Python is an object-oriented programming language that supports multiple inheritance. One of the key challenges with multiple inheritance is determining the order in which base classes are searched when a method or attribute is referenced. This order is defined by the Method Resolution Order (MRO). Understanding MRO is crucial when working with class hierarchies in Python to predict and control method lookups.
This document explores how Python resolves methods and attributes in single and multiple inheritance hierarchies using the C3 Linearization algorithm. We will cover the basics of inheritance, dive deep into how MRO works, explore complex inheritance trees, and discuss best practices.
In single inheritance, a subclass inherits from one superclass.
class A:
def greet(self):
print("Hello from A")
class B(A):
pass
obj = B()
obj.greet() # Output: Hello from A
In multiple inheritance, a subclass inherits from more than one superclass.
class A:
def greet(self):
print("Hello from A")
class B:
def greet(self):
print("Hello from B")
class C(A, B):
pass
obj = C()
obj.greet() # Output: Hello from A
In this example, Python searches for greet in C, then A, and then B. This is determined by MRO.
Method Resolution Order (MRO) is the sequence in which base classes are searched when executing a method or looking up an attribute. Python uses the C3 linearization algorithm to compute the MRO in new-style classes (all classes in Python 3 are new-style).
class A: pass
class B(A): pass
print(B.__mro__)
print(B.mro())
The C3 linearization algorithm ensures a consistent and predictable order of method resolution by following three rules:
It merges the MROs of parent classes and the list of parents in the order they are defined, ensuring all rules are satisfied.
class A:
def show(self):
print("A")
class B(A):
def show(self):
print("B")
b = B()
b.show() # Output: B
print(B.__mro__)
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
class A:
def show(self):
print("A")
class B:
def show(self):
print("B")
class C(A, B):
pass
c = C()
c.show() # Output: A
print(C.mro())
The method is found in A before B because A is listed first in the inheritance list.
class A:
def show(self):
print("A")
class B(A):
def show(self):
print("B")
class C(A):
def show(self):
print("C")
class D(B, C):
pass
d = D()
d.show() # Output: B
print(D.mro())
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
The MRO of D is [D, B, C, A, object]. Python uses the C3 algorithm to resolve this order and avoids ambiguity.
class X: pass
class Y: pass
class A(X, Y): pass
class B(Y, X): pass
# class C(A, B): pass # Will raise TypeError
This raises a TypeError because thereβs no consistent MRO due to conflicting base class orders.
class A:
def show(self):
print("A")
class B(A):
def show(self):
print("B")
super().show()
class C(B):
def show(self):
print("C")
super().show()
c = C()
c.show()
C
B
A
Each class uses super() to call the next method in the MRO chain.
The C3 algorithm ensures that method resolution is deterministic and predictable.
All calls to super() resolve to the next class in the MRO, ensuring consistent behavior in cooperative multiple inheritance.
Using super() ensures that all base classes in the MRO get a chance to contribute.
Prefer composition over deep inheritance hierarchies to avoid complexity and potential MRO conflicts.
Use ClassName.mro() to debug and verify the method resolution order.
class Base:
def process(self):
print("Base process")
class Logger(Base):
def process(self):
print("Logging")
super().process()
class Validator(Base):
def process(self):
print("Validating")
super().process()
class App(Logger, Validator):
def process(self):
print("App logic")
super().process()
a = App()
a.process()
App logic
Logging
Validating
Base process
class MyList(list):
pass
print(MyList.__mro__)
(<class '__main__.MyList'>, <class 'list'>, <class 'object'>)
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Dog(Animal):
def sound(self):
print("Bark")
d = Dog()
d.sound()
print(Dog.__mro__)
Always print the MRO to debug inheritance chains and ensure super() behaves as expected.
Third-party tools and IDEs like PyCharm or VS Code can visualize class hierarchies and MRO.
The Method Resolution Order (MRO) in Python is essential for understanding how Python looks up methods and attributes in class hierarchies. The C3 linearization algorithm provides a deterministic and conflict-free resolution order, particularly important when dealing with multiple inheritance.
By mastering MRO, developers can:
Always inspect and understand the MRO when designing class hierarchies, especially with multiple inheritance. The clarity and power it brings to Python object-oriented design is invaluable for building robust systems.
Python is commonly used for developing websites and software, task automation, data analysis, and data visualisation. Since it's relatively easy to learn, Python has been adopted by many non-programmers, such as accountants and scientists, for a variety of everyday tasks, like organising finances.
Learning Curve: Python is generally considered easier to learn for beginners due to its simplicity, while Java is more complex but provides a deeper understanding of how programming works.
The point is that Java is more complicated to learn than Python. It doesn't matter the order. You will have to do some things in Java that you don't in Python. The general programming skills you learn from using either language will transfer to another.
Read on for tips on how to maximize your learning. In general, it takes around two to six months to learn the fundamentals of Python. But you can learn enough to write your first short program in a matter of minutes. Developing mastery of Python's vast array of libraries can take months or years.
6 Top Tips for Learning Python
The following is a step-by-step guide for beginners interested in learning Python using Windows.
Best YouTube Channels to Learn Python
Write your first Python programStart by writing a simple Python program, such as a classic "Hello, World!" script. This process will help you understand the syntax and structure of Python code.
The average salary for Python Developer is βΉ5,55,000 per year in the India. The average additional cash compensation for a Python Developer is within a range from βΉ3,000 - βΉ1,20,000.
Copyrights © 2024 letsupdateskills All rights reserved