Kodeclik Logo

Learn More

Fall 2025

Kodeclik Blog

Inheritance in Python

When you write code in languages like Python you will find the need to reuse code across functions or parts of your program but in a “derived” manner. This idea is called inheritance and languages like Python provide systematic ways to organize your code to support such reuse of code. The underlying paradigm of computing is called “object oriented programming” or OOP for short.

Table of Contents


What is Inheritance?

The Solution: A Base Class and Subclasses

Example1: Courses and Lab Courses

Python Inheritance in Detail

Understanding super()

Example 2: Vehicles

Summary

What is Inheritance?

Inheritance is a fundamental concept in object-oriented programming where a new class (called a child or subclass) is created based on an existing class (called a parent or superclass). It is easiest explained using an example.

Imagine you're building a system to manage different types of courses at your school. All courses share common characteristics:

  • A course code (like "MATH101")
  • A course name
  • Credit hours
  • An instructor
  • A list of enrolled students

However, some types of courses have unique requirements. For example, a chemistry lab course needs additional information that a regular math course doesn't need:

  • Lab location
  • Lab schedule (day and time)
  • Safety training requirements
  • Tracking which students have completed safety certification

You could create completely separate classes for each course type, but this leads to duplicate code and makes maintenance difficult. What if you need to change how enrollment works? You'd have to update it in multiple places. This is where inheritance comes in.

The Solution: A Base Class and Subclasses

We create a base class called Course that contains all the common functionality every course needs. Then we create subclasses like LabCourse that inherit everything from Course and add their own specialized features. Below is an example where we show the base class and then two examples of subclasses.

Course (base class)
├── LabCourse (subclass) - adds lab-specific features
└── OnlineCourse (subclass) - adds online-specific features

Example1: Courses and Lab Courses

In the below code, we create a base Course class with the common features, then create a LabCourse subclass that inherits everything from Course and adds lab-specific features.

class Course:
    """Base class representing a general academic course"""
    
    def __init__(self, course_code, course_name, instructor):
        self.course_code = course_code
        self.course_name = course_name
        self.instructor = instructor
    
    def display(self):
        print(f"\nCourse: {self.course_code} - {self.course_name}")
        print(f"Instructor: {self.instructor}")


class LabCourse(Course):
    """Subclass for courses that have a lab component"""
    
    def __init__(self, course_code, course_name, instructor, lab_location, lab_day):
        # Call parent class constructor
        super().__init__(course_code, course_name, instructor)
        
        # Additional attributes specific to lab courses
        self.lab_location = lab_location
        self.lab_day = lab_day
    
    def display(self):
        # Call parent's display first
        super().display()
        
        # Add lab-specific information
        print(f"Lab Location: {self.lab_location}")
        print(f"Lab Day: {self.lab_day}")


# Example usage
if __name__ == "__main__":
    # Regular course
    math_course = Course("MATH101", "Calculus I", "Dr. Smith")
    math_course.display()
    
    # Lab course with extra features
    chem_course = LabCourse("CHEM201", "Organic Chemistry", "Dr. Williams", 
                            "Science Building Room 304", "Wednesday")
    chem_course.display()

(Note that we are not using all the attributes or features from the example above, but you get the idea.)

Without inheritance, we would have to copy and paste the same code in both Course and LabCourse, maintaining the same logic in multiple places and risking bugs when we update one class but forget to update the other.

With inheritance, we write common code once in the parent class and automatically get updates to parent functionality in all child classes. This keeps our code organized and maintainable while modeling real-world relationships—a lab course is a course, just with extra features.

This is the power of inheritance: building specialized classes on top of general ones, reusing code while adding exactly what you need. As your programs grow larger and more complex, inheritance becomes essential for managing that complexity and keeping your codebase clean and efficient.

The output of the above program will be:

Course: MATH101 - Calculus I
Instructor: Dr. Smith

Course: CHEM201 - Organic Chemistry
Instructor: Dr. Williams
Lab Location: Science Building Room 304
Lab Day: Wednesday

Note that for both courses we print the course name and the instructor but for the LabCourse (i.e., CHEM201) we also print the lab location and lab day.

Python Inheritance in Detail

When we define a class in Python, we're essentially creating a blueprint or template. The class keyword followed by the class name (like class Course:) tells Python we're defining what a Course should look like and what it can do. Inside the class definition, we list all the attributes (data) and methods (functions) that belong to that class.

The __init__ method is special—it's the constructor that runs automatically whenever we create a new object from the class. Inside __init__, we use self to refer to the specific object being created. When we write self.course_code = course_code, we're taking the value passed as a parameter and storing it as an attribute of that particular object. The self parameter is how Python distinguishes between the class blueprint and the actual objects created from it—it's the way each individual object keeps track of its own data.

Understanding super()

When a child class inherits from a parent class, we often need a way to access the parent's methods and attributes. This is where super() comes in. The super() function is a built-in Python function that gives us a temporary object of the parent class, allowing the child class to call the parent's methods. Think of super() as a way to say "call the parent version of this method" without having to explicitly name the parent class.

In our example, look at the LabCourse.__init__ method. When we write super().__init__(course_code, course_name, instructor), we're telling Python to call the Course.__init__ method to handle setting up the basic course attributes. This is crucial because we don't want to duplicate the code that stores course_code, course_name, and instructor—that logic already exists in the parent class. After super().__init__() runs, the object has all the basic course attributes set up, and then we can add the lab-specific attributes like lab_location and lab_day. Without super(), we would have to manually repeat all the parent's initialization code in every child class, which defeats the purpose of inheritance.

Each class can have its own methods, which are functions that belong to that class and can access its attributes through self. In our example, both Course and LabCourse have a display() method, but these are two distinct methods that should not be confused with each other. The Course.display() method only knows about and prints the basic course information (code, name, instructor), while the LabCourse.display() method knows about both the basic information and the lab-specific information (location and day). Here again, super() proves invaluable: when LabCourse.display() calls super().display(), it's executing the parent's display logic to print the basic course information. Then, after that completes, the child class adds its own print statements for the lab-specific details. This approach ensures we're not copying and pasting the display logic from the parent class.

For instance, when we call chem_course.display(), Python looks at the type of object (LabCourse) and uses that class's version of the method, not the parent's version. This is called method overriding—the child class provides its own implementation while still having the option to use the parent's implementation through super(). The beauty of this system is that you can choose whether to completely replace a parent's method (by not calling super()) or extend it (by calling super() and then adding more functionality). In most cases, extending is preferable because it maintains the parent's behavior while adding specialized behavior.

The relationship between parent and child classes is permanent and hierarchical. Once LabCourse inherits from Course, every LabCourse object automatically has all the attributes and methods that Course has, plus whatever additional ones we define in LabCourse. This means a LabCourse object has course_code, course_name, instructor, lab_location, and lab_day as attributes, while a regular Course object only has the first three. This is why inheritance is so powerful—it allows us to build specialized versions of classes without losing any of the original functionality, and it ensures that changes to the parent class automatically flow down to all child classes.

Example 2: Vehicles

Here’s a second example of inheritance using something everyone is familiar with: vehicles.

Imagine you're building a system to track different types of vehicles. All vehicles share common characteristics:

  • A brand (like "Toyota" or "Honda")
  • A model name
  • A year

However, different types of vehicles have unique features. For example, an electric car needs additional information that a regular car doesn't need:

  • Battery capacity (in kWh)
  • Charging time

Once again, we will create a base Vehicle class with the common features, then create an ElectricCar subclass that inherits everything from Vehicle and adds electric-specific features.

Python inheritance example
class Vehicle:
    """Base class representing a general vehicle"""
    
    def __init__(self, brand, model, year):
        self.brand = brand
        self.model = model
        self.year = year
    
    def display(self):
        print(f"\n{self.year} {self.brand} {self.model}")


class ElectricCar(Vehicle):
    """Subclass for electric vehicles"""
    
    def __init__(self, brand, model, year, battery_capacity, charging_time):
        # Call parent class constructor
        super().__init__(brand, model, year)
        
        # Additional attributes specific to electric cars
        self.battery_capacity = battery_capacity
        self.charging_time = charging_time
    
    def display(self):
        # Call parent's display first
        super().display()
        
        # Add electric car specific information
        print(f"Battery Capacity: {self.battery_capacity} kWh")
        print(f"Charging Time: {self.charging_time} hours")


# Example usage
if __name__ == "__main__":
    # Regular vehicle
    my_car = Vehicle("Honda", "Civic", 2020)
    my_car.display()
    
    # Electric car with extra features
    my_tesla = ElectricCar("Tesla", "Model 3", 2023, 75, 8)
    my_tesla.display()

Once again the output will be:

2020 Honda Civic

2023 Tesla Model 3
Battery Capacity: 75 kWh
Charging Time: 8 hours

Once again, without inheritance, we would have to copy and paste the same code in both Vehicle and ElectricCar, maintaining the same logic in multiple places and risking bugs when we update one class but forget to update the other. With inheritance, we write common code once in the parent class and automatically get updates to parent functionality in all child classes.

Summary

Python inheritance is a cornerstone of object-oriented programming that allows you to create hierarchical relationships between classes, promoting code reuse and maintainability. By defining a base class with common attributes and methods, you can create specialized subclasses that inherit all parent functionality while adding their own unique features.

The key concepts include using the class ChildClass(ParentClass): syntax to establish inheritance, calling super().__init__() to initialize parent attributes, and using super() to access parent methods when overriding them in child classes. Through inheritance, you avoid code duplication, create logical class hierarchies that mirror real-world relationships, and ensure that updates to parent classes automatically propagate to all child classes. Whether you're modeling courses and lab courses, vehicles and electric cars, or any other hierarchical relationship, inheritance provides an elegant solution that scales as your codebase grows, making your programs more organized, efficient, and easier to maintain.

Enjoy this blogpost? Want to learn Python with us? Sign up for 1:1 or small group classes.

Kodeclik sidebar newsletter

Join our mailing list

Subscribe to get updates about our classes, camps, coupons, and more.

About

Kodeclik is an online coding academy for kids and teens to learn real world programming. Kids are introduced to coding in a fun and exciting way and are challeged to higher levels with engaging, high quality content.

Copyright @ Kodeclik 2025. All rights reserved.