Introduction to Inheritance
One of the major benefits of object oriented programming is reuse of code and one of the ways this is achieved is through the inheritance mechanism. Inheritance can be best imagined as implementing a type and subtype relationship between classes.
What Inheritance Solves
Imagine you are building a library system with different types of items: books, DVDs, and audiobooks. Each has a title, an author, and a publication year. Without inheritance, you would write the same code to store and manage these properties three separate times. Inheritance lets you write that common code once in a parent class and reuse it across all three item types. This is one of the major benefits of object-oriented programming: code reuse through the inheritance mechanism.
Inheritance implements a type and subtype relationship between classes. A parent class (or base class) defines shared properties and behavior. A child class (or derived class) inherits those properties and behavior, and can add its own specialized features.
Type and Subtype Relationships
In the real world, a type-subtype relationship is familiar: a dog is a type of animal, a sedan is a type of car, a novel is a type of book. In object-oriented programming, inheritance mirrors this relationship. The parent class represents the general type (Animal, Vehicle, Book), and child classes represent more specific subtypes (Dog, Sedan, Novel). The child class inherits all the properties and methods of the parent, so a Dog automatically has all the attributes and behaviors of an Animal, but can add dog-specific features like a breed or a bark method.
How Inheritance Works in Python
To use inheritance in Python, you specify the base class name in parentheses after the class name in the class definition. For example, class Book(Item) means that Book inherits from Item. When you create an instance of Book, it automatically has access to all the properties and methods defined in Item. However, there is a critical step: you must explicitly call the base class constructor using the self variable. Python does not automatically call the constructor of the base class—you have to call it yourself.
Explicit base class constructor initialization is very important to remember. If you do not call the parent class __init__ method, the parent class part of the object will not be properly initialized, and your child class instance may not work as expected.
A Worked Example: Library Items
Creating a Parent and Child Class
Design a library system where a base Item class stores common information (title, author, publication year), and a Book class inherits from Item and adds book-specific information (ISBN, number of pages). Show how to properly initialize both the parent and child class.
Define the parent class Item: The Item class has an __init__ method that accepts title, author, and year. These are the common properties shared by all library items.
Define the child class Book: The Book class inherits from Item by writing class Book(Item). In its __init__ method, it accepts all the parent parameters plus its own (isbn and pages).
Call the parent constructor explicitly: Inside Book.__init__, we call Item.__init__(self, title, author, year) or use super().__init__(title, author, year). This ensures the parent class part of the object is initialized.
Add child-specific attributes: After calling the parent constructor, we set self.isbn and self.pages, which are unique to the Book class.
Create an instance and verify: When we create a Book instance, it has both the inherited attributes (title, author, year) and its own attributes (isbn, pages).
A Book instance successfully inherits from Item and adds its own specialized properties without code duplication.
1984
George Orwell
978-0451524935
328Code Reuse Through Inheritance
Notice how the after version eliminates the duplication of title, author, and year initialization across all three classes. If you later need to change how these common properties are initialized, you only change the Item class once, and all child classes automatically benefit from the change.
Multiple Inheritance
If more than one class is listed in the inheritance tuple, it is called multiple inheritance. For example, class Hybrid(Car, Electric) means that Hybrid inherits from both Car and Electric. This allows a class to combine behavior and properties from multiple parent classes. However, multiple inheritance can introduce complexity, especially when both parent classes define the same method or attribute. Most introductory projects use single inheritance (one parent class), but it is useful to know that multiple inheritance exists.
Toyota
50
GasolineCommon Mistakes with Inheritance
Forgetting to call the parent class constructor
The parent class attributes (like title) are never initialized. When you try to access my_book.title, you get an AttributeError because title was never set.
Fix:
Always explicitly call the parent constructor: Item.__init__(self, title, author, year) or use super().__init__(title, author, year)Assuming Python automatically calls the parent constructor
Python does not automatically call the base class __init__. You must call it explicitly, or the parent class part of the object will not be initialized.
Fix:
Explicitly call Item.__init__(self, title, author, year) inside Book.__init__Forgetting to pass self as the first argument when calling the parent constructor
Without self, Python does not know which instance to initialize. You will get a TypeError about the number of arguments.
Fix:
Always pass self: Item.__init__(self, title, author, year)Confusing the order of parent classes in multiple inheritance
In multiple inheritance, the order of parent classes affects method resolution. If both parents define the same method, the leftmost parent's version is used. Putting them in the wrong order can lead to unexpected behavior.
Fix:
Understand the method resolution order (MRO) and list parent classes in the order that makes logical sense for your design
Why Inheritance Matters
In a real web application, you might have a User class that stores username, email, and password. Then you create Admin and Customer subclasses that inherit from User. Both Admin and Customer need the same basic user information, but Admin might have additional permissions, and Customer might have a purchase history. Without inheritance, you would duplicate the username, email, and password code in both Admin and Customer. With inheritance, you write it once in User, and both subclasses automatically have it. If you later need to add a phone number field to all users, you add it to the User class once, and it immediately applies to Admin and Customer without changing their code.
Inheritance is not just about saving lines of code. It is about expressing a logical relationship: Admin is a type of User, Customer is a type of User. This makes your code clearer, easier to maintain, and easier to extend with new subtypes in the future.
Practice: Build Your Own Inheritance
Create a parent class Animal with attributes name and age, and an __init__ method that initializes both. Then create two child classes: Dog and Cat. Dog should inherit from Animal and add a breed attribute. Cat should inherit from Animal and add a color attribute. For each child class, make sure to explicitly call the parent constructor. Create one instance of Dog and one instance of Cat, and verify that both have access to the inherited name and age attributes as well as their own specialized attributes.
Hints
- Remember to use the syntax class Dog(Animal) to indicate inheritance
- Inside Dog.__init__, call Animal.__init__(self, name, age) before setting the breed attribute
- Test your code by printing both inherited and child-specific attributes
Key Takeaways
- Inheritance implements a type and subtype relationship between classes, allowing child classes to inherit properties and methods from a parent class.
- The primary benefit of inheritance is code reuse: common code is written once in the parent class and automatically available to all child classes.
- In Python, you specify inheritance by listing the parent class in parentheses after the class name: class Child(Parent).
- You must explicitly call the parent class constructor using self; Python does not automatically initialize the parent class part of the object.
- Multiple inheritance allows a class to inherit from more than one parent class, though it introduces additional complexity and is less common in introductory projects.