How to inherit a class in Python
Learn how to inherit a class in Python. This guide covers methods, tips, real-world applications, and common errors to help you master it.

Class inheritance is a core concept in Python's object-oriented programming. It allows you to build new classes that reuse and extend functionality from existing ones for cleaner, more organized code.
Here, you'll explore essential techniques and practical tips for class inheritance. You'll also find real-world applications and debugging advice to help you confidently implement this powerful feature.
Basic inheritance syntax
class Parent:
def greet(self):
return "Hello from Parent"
class Child(Parent):
pass
child = Child()
print(child.greet())--OUTPUT--Hello from Parent
The core of inheritance lies in the declaration class Child(Parent):. Placing the parent class inside the parentheses grants the child class access to its methods and attributes. This is why an instance of Child can successfully call the greet() method, even though it's defined in the Parent class. Understanding the fundamentals of creating a class in Python is essential before exploring inheritance.
- The
passkeyword simply means theChildclass doesn't add any new functionality—it's a placeholder. - This structure allows you to reuse code effectively, creating a new class that inherits a complete set of behaviors without any duplication.
Core inheritance concepts
Building on this foundation, you can manage more complex class relationships by overriding methods, accessing parent functionality with super(), and inheriting from multiple parents.
Accessing parent class methods with super()
class Animal:
def make_sound(self):
return "Some generic sound"
class Dog(Animal):
def make_sound(self):
parent_sound = super().make_sound()
return f"{parent_sound} and a bark"
dog = Dog()
print(dog.make_sound())--OUTPUT--Some generic sound and a bark
The super() function is your tool for accessing methods from a parent class, even when you've overridden them. In this example, the Dog class provides its own make_sound() method, but it doesn't want to lose the original Animal functionality entirely. For more detailed techniques on using super() in Python, explore advanced patterns and best practices.
- By calling
super().make_sound(), you execute the parent's method first. - This allows you to build upon the parent's logic—in this case, adding a "bark" to the "generic sound"—rather than replacing it completely. It's a powerful way to extend functionality.
Method overriding in child classes
class Vehicle:
def max_speed(self):
return "Generic vehicle speed"
class Car(Vehicle):
def max_speed(self):
return "120 mph"
car = Car()
print(car.max_speed())--OUTPUT--120 mph
Method overriding occurs when a child class provides a specific implementation for a method that's already defined in its parent. Here, the Car class defines its own max_speed() method, which takes precedence over the one in the Vehicle class.
- This allows you to create specialized behavior. When you call the method on a
Carobject, Python executes the child's version, effectively replacing the parent's more generic logic.
Multiple inheritance
class Flyable:
def fly(self):
return "I can fly"
class Swimmable:
def swim(self):
return "I can swim"
class Duck(Flyable, Swimmable):
pass
duck = Duck()
print(duck.fly())
print(duck.swim())--OUTPUT--I can fly
I can swim
Python isn't limited to single-parent inheritance; you can combine behaviors from multiple classes. By declaring class Duck(Flyable, Swimmable):, the Duck class inherits methods from both parents, allowing you to create composite classes that blend distinct functionalities.
- An instance of
Duckcan call bothfly()andswim(), even though its own class definition is empty. - This approach is great for mixing and matching behaviors—like different types of movement—without duplicating code.
Advanced inheritance techniques
Building on concepts like multiple inheritance, you can create more robust designs using abstract base classes, mixins, and by understanding Python's Method Resolution Order.
Using abstract base classes
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
square = Square(5)
print(f"Area: {square.area()}")--OUTPUT--Area: 25
An abstract base class (ABC) acts as a blueprint, defining methods that child classes must implement. By inheriting from ABC and using the @abstractmethod decorator, the Shape class establishes a contract. It guarantees that any subclass will have an area() method.
- This structure enforces a consistent interface. You can't create an instance of
Shapedirectly. - Any child class, like
Square, is required to provide its ownarea()implementation. If it doesn't, Python raises an error, ensuring all shapes are guaranteed to have this functionality.
Implementing mixin classes
class JSONSerializableMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class User(JSONSerializableMixin):
def __init__(self, name, age):
self.name = name
self.age = age
user = User("Alice", 30)
print(user.to_json())--OUTPUT--{"name": "Alice", "age": 30}
A mixin is a class designed to add a specific feature to other classes without being a parent in the traditional sense. Think of it as plugging in a piece of functionality. Here, the JSONSerializableMixin provides a reusable to_json() method that any class can adopt, leveraging techniques for converting dictionaries to JSON.
- By inheriting from the mixin, the
Userclass instantly gains the ability to serialize itself to JSON. - This approach keeps the
Userclass focused on its main job—managing user data—while the mixin handles the separate concern of JSON conversion. It's a clean way to share functionality across unrelated classes.
Understanding Method Resolution Order (MRO)
class A:
def who_am_i(self):
return "Class A"
class B(A):
def who_am_i(self):
return "Class B"
class C(A):
def who_am_i(self):
return "Class C"
class D(B, C):
pass
d = D()
print(d.who_am_i())
print(D.__mro__)--OUTPUT--Class B
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
Method Resolution Order (MRO) is the rule Python follows to determine which method to run in complex inheritance chains. When a class like D inherits from multiple parents—in this case, B and C—Python needs a clear path to resolve method calls, avoiding ambiguity.
- The
__mro__attribute reveals this exact path. For classD, the order isD,B,C, and finallyA. - When you call
d.who_am_i(), Python checksDfirst, finds nothing, then moves toB. SinceBhas the method, its version is executed and the search ends.
Move faster with Replit
Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. Describe what you want to build, and Agent 4 handles everything—from writing the code and connecting databases to deploying it live.
Instead of piecing together techniques, you can describe the app you actually want to build and let the Agent take it from idea to working product:
- A unit converter where different classes like
LengthConverterandWeightConverterinherit from a baseConverter, each providing a specializedconvert()method. - A UI component library where a
JSONMixinadds export functionality to different widget classes likeButtonandSlider. - A notification system where
EmailNotifierandSMSNotifierextend a base class, usingsuper()to add delivery logic to a shared message formatting method.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
Even with a solid grasp of inheritance, you'll run into a few common pitfalls that can be tricky to debug and may require code repair techniques.
Debugging misspelled method names when overriding
A simple typo is one of the most frequent sources of bugs when overriding methods. If you intend to override a parent method but misspell its name in the child class, Python won't raise an error. Instead, it treats your misspelled version as a brand new method, and any calls to the original method name will silently execute the parent's version, leading to behavior you didn't expect.
Resolving method conflicts in multiple inheritance
When a class inherits from multiple parents that have methods with the same name, it can be unclear which one gets called. Python resolves this using the Method Resolution Order (MRO). If your code isn't behaving as expected, the conflict likely lies here. You can inspect the `__mro__` attribute of your class to see the exact lookup order Python uses and identify which parent's method is taking precedence.
Troubleshooting incomplete abstract class implementations
Abstract base classes enforce a contract that requires subclasses to implement specific methods. If you forget to implement any method marked with the @abstractmethod decorator, Python will stop you from creating an instance of that subclass by raising a TypeError. The error message is usually quite helpful—it will explicitly tell you which abstract methods are still undefined, making the fix straightforward.
Debugging misspelled method names when overriding
It's easy to misspell a method name when you're overriding it, which creates a subtle bug. Python won't throw an error; it just runs the parent's method instead of yours. The code below shows how this silent failure can happen.
class Parent:
def process_data(self, data):
return f"Processing {data}"
class Child(Parent):
# Misspelled method name - not actually overriding
def proccess_data(self, data):
return f"Child processing {data}"
child = Child()
print(child.process_data("sample")) # Uses Parent's method
The Child class defines proccess_data, but the call is for process_data. Since the names don't match, Python executes the Parent's method instead, silently ignoring the intended override. The following code demonstrates the correct implementation.
class Parent:
def process_data(self, data):
return f"Processing {data}"
class Child(Parent):
# Correct method name for overriding
def process_data(self, data):
return f"Child processing {data}"
child = Child()
print(child.process_data("sample")) # Uses Child's method
By correcting the typo to process_data, the Child class now successfully overrides the parent's method. When you call child.process_data("sample"), Python finds the matching method in the child and executes it, giving you the specialized behavior you intended. This kind of silent failure is common, so always double-check your method names when overriding—especially if the parent's logic runs unexpectedly.
Resolving method conflicts in multiple inheritance
When you combine classes that share method names, like execute(), Python doesn't get confused—it simply follows a predictable order to decide which one to run. This can lead to silent bugs where the wrong method is called, as you'll see below.
class Service1:
def execute(self):
return "Service 1 execution"
class Service2:
def execute(self):
return "Service 2 execution"
class CombinedService(Service1, Service2):
pass
service = CombinedService()
print(service.execute()) # Only calls Service1's method
Because CombinedService inherits from Service1 first, Python calls its execute() method and ignores the version in Service2. This can hide functionality unexpectedly. The following example demonstrates how to resolve this conflict.
class Service1:
def execute(self):
return "Service 1 execution"
class Service2:
def execute(self):
return "Service 2 execution"
class CombinedService(Service1, Service2):
def execute(self):
s1_result = Service1.execute(self)
s2_result = Service2.execute(self)
return f"{s1_result} and {s2_result}"
service = CombinedService()
print(service.execute())
The solution is to override the conflicting method in the child class. By defining a new execute() method in CombinedService, you can explicitly call each parent's version using Service1.execute(self) and Service2.execute(self). This lets you combine their results instead of letting one silently override the other. Keep an eye on this when using mixins or inheriting from multiple third-party libraries, where method name clashes are more likely.
Troubleshooting incomplete abstract class implementations
Abstract base classes enforce a contract that requires child classes to implement specific methods. If you forget even one, Python won't let you create an object from your class, raising a TypeError because the contract is broken. The code below shows what happens when a class inherits from a Database ABC but fails to implement the required query() method.
from abc import ABC, abstractmethod
class Database(ABC):
@abstractmethod
def connect(self):
pass
@abstractmethod
def query(self, sql):
pass
class SQLiteDB(Database):
def connect(self):
return "Connected to SQLite"
# Missing query method implementation
db = SQLiteDB() # Will raise TypeError
Because the SQLiteDB class doesn't implement the required query() method, it breaks the contract set by the abstract class. This causes a TypeError when you try to create an instance. The following example provides the necessary implementation.
from abc import ABC, abstractmethod
class Database(ABC):
@abstractmethod
def connect(self):
pass
@abstractmethod
def query(self, sql):
pass
class SQLiteDB(Database):
def connect(self):
return "Connected to SQLite"
def query(self, sql):
return f"Executing: {sql}"
db = SQLiteDB()
print(db.connect())
print(db.query("SELECT * FROM users"))
By implementing the missing query() method, the SQLiteDB class now fulfills the contract required by its abstract parent. This fixes the TypeError and makes the class instantiable. You'll run into this when working with frameworks or plugin architectures that demand specific methods be present, ensuring all components behave predictably. This approach guarantees a consistent API across different implementations.
Real-world applications
Beyond the syntax and debugging, inheritance is a powerful tool for structuring complex applications like data processors and game frameworks, especially when combined with vibe coding approaches.
Building a data processor hierarchy with inheritance
Inheritance lets you build a flexible hierarchy for handling different data formats by creating a base DataProcessor for shared logic and letting subclasses override specific methods like parse().
class DataProcessor:
def process(self, data):
cleaned_data = self.clean(data)
return self.parse(cleaned_data)
def clean(self, data):
return data.strip()
def parse(self, data):
return data # Default implementation
class CSVProcessor(DataProcessor):
def parse(self, data):
lines = data.split('\n')
return [line.split(',') for line in lines]
# Example usage
csv_processor = CSVProcessor()
sample_data = "name,age\nAlice,30\nBob,25"
result = csv_processor.process(sample_data)
print(result)
The DataProcessor class establishes a two-step workflow in its process() method, which calls clean() and then parse(). The CSVProcessor inherits this entire workflow but provides its own specialized version of the parse() method to handle comma-separated data. For more robust CSV handling, explore comprehensive techniques for reading CSV files in Python.
- When you call
process()on aCSVProcessorobject, it executes the sharedclean()logic from the parent. - It then runs its own custom
parse()implementation, effectively reusing the overall processing steps while tailoring a specific part for a different data type.
Creating a simple game framework with inheritance
You can structure a simple game by creating a base GameObject with update() and draw() methods, allowing subclasses like Player to inherit this framework and add their own unique features.
class GameObject:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def update(self):
pass
def draw(self):
print(f"Drawing object at ({self.x}, {self.y})")
class Player(GameObject):
def __init__(self, x=0, y=0, health=100):
super().__init__(x, y)
self.health = health
def update(self):
self.health = min(100, self.health + 1) # Regenerate health
def draw(self):
print(f"Drawing player at ({self.x}, {self.y}) with health: {self.health}")
player = Player(10, 20, 80)
for _ in range(2):
player.update()
player.draw()
The Player class inherits core position tracking from GameObject but gives it a unique purpose. It calls super().__init__() to handle the initial x and y setup, then adds its own health attribute for game-specific logic. Both the update() and draw() methods are overridden to create specialized behavior.
- The
Player'supdate()method implements health regeneration, replacing the empty method from the parent. - Its custom
draw()method provides more detailed output by including the current health, making it more useful than the generic parent version.
Get started with Replit
Turn your knowledge into a real tool. Describe what you want to build to Replit Agent, like “a unit converter with a base class and subclasses for length and weight” or “a data parser for CSV and JSON files.”
Replit Agent will write the code, test for errors, and deploy your application. Start building with Replit.
Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.
Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.



