For working professionals
For fresh graduates
More
13. Print In Python
15. Python for Loop
19. Break in Python
23. Float in Python
25. List in Python
27. Tuples in Python
29. Set in Python
53. Python Modules
57. Python Packages
59. Class in Python
61. Object in Python
73. JSON Python
79. Python Threading
84. Map in Python
85. Filter in Python
86. Eval in Python
96. Sort in Python
101. Datetime Python
103. 2D Array in Python
104. Abs in Python
105. Advantages of Python
107. Append in Python
110. Assert in Python
113. Bool in Python
115. chr in Python
118. Count in python
119. Counter in Python
121. Datetime in Python
122. Extend in Python
123. F-string in Python
125. Format in Python
131. Index in Python
132. Interface in Python
134. Isalpha in Python
136. Iterator in Python
137. Join in Python
140. Literals in Python
141. Matplotlib
144. Modulus in Python
147. OpenCV Python
149. ord in Python
150. Palindrome in Python
151. Pass in Python
156. Python Arrays
158. Python Frameworks
160. Python IDE
164. Python PIP
165. Python Seaborn
166. Python Slicing
168. Queue in Python
169. Replace in Python
173. Stack in Python
174. scikit-learn
175. Selenium with Python
176. Self in Python
177. Sleep in Python
179. Split in Python
184. Strip in Python
185. Subprocess in Python
186. Substring in Python
195. What is Pygame
197. XOR in Python
198. Yield in Python
199. Zip in Python
In the world of object-oriented programming, inheritance is the magical rope that ties generations of code together—just like how your surname ties you to your family lineage. Whether you're a beginner learning Python or preparing for that campus placement interview, understanding inheritance isn't just helpful—it's essential. It allows classes to borrow properties and behavior from other classes, reducing redundancy and making your code more modular, efficient, and elegant. In short, inheritance lets you write less but do more.
Imagine your father, Rajat, being a proud owner of a Royal Enfield, and you—his daughter, Arushi—inheriting not just the bike but also his biking skills and road sense. You didn’t have to start from scratch; you simply inherited the goodies. Similarly, classes in Python can inherit attributes and methods from other classes. This forms the backbone of object-oriented design in Python and helps in building complex programs that are easy to understand and maintain. Let's dive into the mechanics of inheritance in Python, one concept at a time—starting with what it really means.
Pursue our Software Engineering courses to get hands-on experience!
In simple terms, Inheritance in Python allows one class (called the child class or subclass) to derive the properties and behaviors of another class (called the parent class or superclass). This helps you avoid duplicating code and encourages code reusability—something every smart developer strives for. Think of it like a ready-made dosa batter—why grind from scratch when you can build on what's already there?
Python supports inheritance right out of the box, making it an essential part of its object-oriented programming features. You can use inheritance to extend or customize existing classes without altering them, which keeps your base logic intact and your subclasses flexible.
Step up your game by exploring these high-impact programs.
Let’s look at a simple example to bring the concept to life:
Example: Basic Inheritance
class Father:
def skills(self):
print("Can drive and cook.")
class Son(Father):
pass
aniket = Son()
aniket.skills()
Output:
Can drive and cook.
Explanation: The Son class inherits from the Father class. Since it doesn’t define its own skills() method, it automatically uses the one from Father. No code duplication, no fuss—just pure Python elegance.
Inheritance in Python operates through a mechanism called the method resolution order (MRO). When you create a subclass that inherits from a parent class, Python follows a specific order to look up attributes and methods. If the subclass doesn’t have a method or attribute, Python checks its parent class, then the parent’s parent, and so on, until it either finds the requested method or raises an error.
Think of it as a family tree search: if your name isn’t on the guest list, you ask your parents, and if they don’t know, you ask your grandparents, until someone knows the answer. This order helps Python efficiently find the right method to call and ensures your code behaves predictably.
Python stores this lookup order in the __mro__ attribute (Method Resolution Order). Let’s see a quick example to understand this better.
Example: Understanding Method Resolution Order (MRO)
class Grandfather:
def heritage(self):
print("Inheritance from Grandfather")
class Father(Grandfather):
def heritage(self):
print("Inheritance from Father")
class Son(Father):
pass
sarthak = Son()
sarthak.heritage()
print(Son.__mro__)
Output:
Inheritance from Father
(<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Grandfather'>, <class 'object'>)
Explanation:
Understanding how Python handles attribute lookup will also help when dealing with instance variables in Python, which are often inherited or overridden.
Inheritance in Python comes in several flavors, each suited to different scenarios. Understanding these types helps you design your classes efficiently and avoid common pitfalls.
A child class inherits from a single parent class.
class Father:
def skills(self):
print("Father can drive.")
class Son(Father):
pass
vicky = Son()
vicky.skills()
Output:
Father can drive.
Explanation: The Son class inherits from Father. Since Son does not have its own skills() method, it uses the one from Father. This is the simplest form of inheritance—one child, one parent.
A child class inherits from more than one parent class.
class Mother:
def cooking(self):
print("Mother can cook.")
class Father:
def driving(self):
print("Father can drive.")
class Child(Mother, Father):
pass
pooja = Child()
pooja.cooking()
pooja.driving()
Output:
Mother can cook.
Father can drive.
Explanation: The Child class inherits from both Mother and Father. It gains access to methods from both parents, showcasing multiple inheritance.
A child class inherits from a parent class, which itself inherits from another parent class, forming a chain.
class Grandfather:
def gardening(self):
print("Grandfather can garden.")
class Father(Grandfather):
def driving(self):
print("Father can drive.")
class Son(Father):
pass
sarthak = Son()
sarthak.gardening()
sarthak.driving()
Output:
Grandfather can garden.
Father can drive.
Explanation: Son inherits from Father, which in turn inherits from Grandfather. This chain represents multilevel inheritance.
Multiple child classes inherit from a single parent class.
class Father:
def skills(self):
print("Father can drive.")
class Son(Father):
pass
class Daughter(Father):
pass
prasun = Son()
arushi = Daughter()
prasun.skills()
arushi.skills()
Output:
Father can drive.
Father can drive.
Explanation: Multiple child classes (Son and Daughter) inherit from a single parent class (Father). Both have access to the same skills() method.
A combination of two or more types of inheritance.
class Mother:
def cooking(self):
print("Mother can cook.")
class Father:
def driving(self):
print("Father can drive.")
class Child1(Mother):
pass
class Child2(Father):
pass
class GrandChild(Child1, Child2):
pass
sarita = GrandChild()
sarita.cooking()
sarita.driving()
Output:
Mother can cook.
Father can drive.
Explanation: Hybrid inheritance combines multiple and multilevel inheritance. Here, GrandChild inherits from two classes, which themselves inherit from different parents.
If you're not yet confident about how methods are defined and reused, brush up with our guide on functions in Python—they’re the building blocks you’ll be extending through inheritance.
To truly grasp inheritance, it helps to connect it with everyday life. Imagine Rajat, who learns cooking skills from his mother and driving skills from his father. In Python, Rajat’s abilities can be modeled with inheritance, where his class inherits traits from both parents.
Let’s see how you can implement this in Python with real-life examples that are easy to relate to.
class Mother:
def cooking(self):
print("Mother can cook traditional Indian meals.")
class Father:
def driving(self):
print("Father can drive a car.")
class Rajat(Mother, Father):
pass
rajat = Rajat()
rajat.cooking()
rajat.driving()
Output:
Mother can cook traditional Indian meals.
Father can drive a car.
Explanation: The Rajat class inherits from both Mother and Father. This means Rajat can both cook and drive without defining these methods himself. This is a practical use of multiple inheritance, showing how Python lets you combine traits easily.
Rajat also learns how to code, a skill unique to him. Let’s add that:
class Rajat(Mother, Father):
def coding(self):
print("Rajat can code in Python.")
rajat = Rajat()
rajat.coding()
Output:
Rajat can code in Python.
Explanation: Here, the Rajat class extends inherited abilities by adding a new method coding(). This shows how child classes can add their own unique features on top of inherited ones.
Suppose Rajat is a better cook than his mother, and he wants to show that. He can override the cooking() method:
class Rajat(Mother, Father):
def cooking(self):
print("Rajat cooks fusion dishes.")
rajat = Rajat()
rajat.cooking()
Output:
Rajat cooks fusion dishes.
Explanation: By redefining the cooking() method, Rajat overrides the parent’s method. This is called method overriding—a powerful feature to customize inherited behavior.
The super() function is like a polite middleman—it helps a child class call methods from its parent class without explicitly naming the parent. This is especially handy when you want to extend or modify parent behavior while still preserving the original functionality.
Example: Using super() to Extend Parent Methods
class Father:
def skills(self):
print("Father can drive.")
class Rajat(Father):
def skills(self):
print("Rajat is learning new skills.")
super().skills()
rajat = Rajat()
rajat.skills()
Output:
Rajat is learning new skills.
Father can drive.
Explanation: In this example, Rajat overrides the skills() method but uses super().skills() to call the original method from Father. This allows Rajat to add his own message before or after the parent’s method runs.
Method overriding allows a child class to provide a specific implementation of a method that is already defined in its parent class. This is crucial when the child class needs to modify or enhance the behavior inherited from the parent.
Overriding is used when the default behavior of a parent class method does not fit the child class’s requirements. For example, imagine Priya inherits a method to greet people formally, but Priya wants to greet with a more casual tone. She can override the method in her child class to customize it without altering the parent class.
Overriding promotes flexibility and polymorphism, allowing different classes to respond differently to the same method call.
Example
class Father:
def greet(self):
print("Good morning, sir!")
class Priya(Father):
def greet(self):
print("Hey! What's up?")
priya = Priya()
priya.greet()
Output:
Hey! What's up?
Explanation: Although Priya inherits from Father, it overrides the greet() method. When calling priya.greet(), Python uses the child class’s version, showing the power of method overriding to customize behavior.
Constructors play a vital role in initializing objects. When inheritance comes into play, understanding how constructors behave and how to properly chain them using super() is essential to avoid unexpected results.
In Python, the __init__ method acts as a constructor. When a child class inherits from a parent class, the parent’s constructor is not called automatically unless you explicitly call it. This can lead to partially initialized objects if you miss invoking the parent constructor.
Using super().__init__() allows the child class to call the parent class’s constructor, ensuring all necessary initialization happens in the right order — a process known as constructor chaining.
Example: Constructor Chaining with super()
class Father:
def __init__(self):
print("Father's constructor called")
class Rajat(Father):
def __init__(self):
super().__init__()
print("Rajat's constructor called")
rajat = Rajat()
Output:
Father's constructor called
Rajat's constructor called
Explanation: Here, Rajat explicitly calls the parent Father’s constructor using super().__init__(). This ensures both constructors run in sequence, properly initializing the object.
Inheritance can feel like climbing a steep hill—challenging at first, but rewarding once you reach the top. Here are some student-friendly tips to make your inheritance journey smoother and more effective:
1. Understand “Is-A” Relationship Clearly
Before using inheritance, ask yourself: Is the child truly a type of the parent? For example, a Son is a Father’s child, so inheritance fits. But a Car is not a Person—don’t force inheritance where it doesn’t logically belong.
2. Keep Your Classes Focused and Simple
Don’t create mega parent classes with too many responsibilities. Follow the Single Responsibility Principle — it keeps your code clean and easy to debug.
3. Use super() Smartly
Always prefer super() to call parent methods, especially constructors. It avoids hard-coding parent class names and supports multiple inheritance without breaking code.
4. Avoid Deep Inheritance Trees
Long inheritance chains can confuse even experienced coders. If you find yourself with many levels, consider composition or interfaces instead of inheritance.
5. Practice with Real-Life Indian Examples
Try modeling things around you—like school classes, family relations (Rajat, Priya, Anjali), or even cricket teams. This contextual practice solidifies concepts better than abstract examples.
6. Watch Out for Method Overriding Pitfalls
Be careful when overriding methods—if you override a method but forget to call the parent version when needed, you might lose important functionality.
Pro Tip: Think of inheritance as your family legacy — use it to build on the past, but don’t let it chain you down! Write clean, readable code that future you (or your friends) will thank you for.
Inheritance is easier to practice once you’re confident in using object-oriented programming in Python. It covers principles that apply directly to your use cases here.
Inheritance in Python is a cornerstone of object-oriented programming that empowers you to build modular, reusable, and scalable code. It mirrors real-life relationships, making your programs easier to design and understand. By mastering inheritance, you unlock the ability to create elegant hierarchies where child classes extend or customize parent class behavior efficiently.
Remember, while inheritance offers immense power, it demands disciplined use—stick to clear “is-a” relationships, leverage super() for clean constructor and method chaining, and avoid deep inheritance trees that complicate your codebase. With these best practices, you’ll not only write better code but also think like a seasoned developer.
So, take a leaf from Rajat, Priya, and their families—inherit the best, innovate boldly, and keep your Python codebase both robust and readable!
Now that you've tackled inheritance, why not explore encapsulation in Python—another core pillar of OOP that goes hand-in-hand with inheritance.
Inheritance allows a child class to inherit attributes and methods from a parent class, enabling code reuse and hierarchical relationships.
Method overriding lets a child class provide a specific implementation of a method already defined in its parent, allowing customization of inherited behavior.
Use inheritance when there is a clear “is-a” relationship between classes. Use composition when you want to build complex objects by combining simpler ones without inheriting from them.
The Diamond Problem occurs in multiple inheritance when two parent classes inherit from the same base class, causing ambiguity. Python solves this using the Method Resolution Order (__mro__), which defines the order in which classes are searched.
super() allows child classes to call methods from their parent classes, facilitating constructor chaining and method extension without explicitly naming parent classes.
If you omit calling the parent constructor, the parent’s initialization code won’t run, potentially leaving your object partially initialized and causing bugs.
issubclass(Sub, Parent) checks if Sub is a subclass of Parent. isinstance(obj, Class) checks if obj is an instance of Class or its subclasses.
__mro__ (Method Resolution Order) shows the order Python uses to look up methods in a class hierarchy, especially important in multiple inheritance to avoid ambiguity.
Yes, if not handled carefully, multiple inheritance can create complex and confusing hierarchies, especially without understanding MRO and super(). Always design with clarity.
Common mistakes include overusing inheritance, deep inheritance trees, forgetting to call parent constructors, and overriding methods without calling the parent version when needed.
Parent constructors are not called automatically in Python inheritance; you must explicitly call them using super() or by directly invoking the parent’s __init__.
Constructor chaining is the practice of calling parent constructors from child constructors using super(), ensuring all parts of the object are properly initialized.
The “is-a” relationship ensures logical correctness. Only use inheritance when a child truly is a type of the parent, avoiding forced or incorrect class hierarchies.
Yes, by overriding the method and calling the parent’s version using super(), you can extend or modify behavior without losing the original implementation.
Keep inheritance shallow and focused, prefer composition when appropriate, use clear naming, always call parent constructors, and leverage super() to maintain clean, maintainable code
Take our Free Quiz on Python
Answer quick questions and assess your Python knowledge
Author|900 articles published
Previous
Next
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918068792934
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.