Introduction
Inheritance lets a new class, called a subclass or child class, derive attributes and methods from an existing class, called a superclass or parent class. This models 'is-a' relationships and enables code reuse: instead of rewriting shared behavior, a subclass extends the parent and adds or modifies only what makes it different. Python supports single inheritance (one direct parent, the focus of this lesson) as well as multiple inheritance, but the core mechanics are best understood through the single-inheritance case first.
Cricket analogy: A T20 format 'is-a' cricket match, inheriting the core rules of bowling and batting from the general game while adding its own specific overs-limit and powerplay rules on top.
Explanation
A subclass is declared by listing the parent class in parentheses: class Dog(Animal):. Inside the subclass's __init__, calling super().__init__(...) invokes the parent class's constructor, letting the subclass reuse the parent's initialization logic instead of duplicating it, while still adding its own subclass-specific attributes afterward. Method overriding occurs when a subclass defines a method with the same name as one in its parent, replacing the parent's implementation for instances of the subclass; the subclass method can still call the parent's version explicitly via super().method_name() if it wants to extend rather than fully replace the behavior. It is important to distinguish overriding from overloading: overloading means defining multiple methods with the same name but different parameter signatures (different number or type of arguments) within the same class, and Python does not support true overloading — if you define two methods with the same name in one class, the second definition simply replaces the first. Python instead achieves overloading-like flexibility through default argument values, *args/**kwargs, or the functools.singledispatch decorator, but that is a distinct mechanism from what languages like Java call method overloading.
Cricket analogy: A young all-rounder joining the national team calls on the senior coach's foundational batting drills (super().__init__) before adding their own signature bowling variation; if they bat exactly like a specialist opener but with an extra reverse-sweep, that's overriding, not overloading, since you can't have two 'bat()' methods with different argument counts on the same player.
Example
class Animal:
def __init__(self, name, sound="..."):
self.name = name
self.sound = sound
def speak(self):
return f"{self.name} says {self.sound}"
def describe(self):
return f"I am an animal named {self.name}"
class Dog(Animal): # single inheritance: Dog derives from Animal
def __init__(self, name, breed):
super().__init__(name, sound="Woof") # reuse parent constructor
self.breed = breed
def speak(self): # method overriding: replaces Animal.speak
base = super().speak() # still calls the parent's version
return f"{base} (a {self.breed})"
generic = Animal("Creature")
rex = Dog("Rex", "Labrador")
print(generic.speak()) # Creature says ...
print(rex.speak()) # Rex says Woof (a Labrador)
print(rex.describe()) # Inherited unchanged from Animal
print(isinstance(rex, Animal)) # True -- Dog is-a AnimalAnalysis
Dog(Animal) establishes single inheritance: Dog has exactly one direct parent, Animal. Inside Dog.__init__, super().__init__(name, sound="Woof") calls Animal.__init__, so self.name and self.sound are set using the parent's logic; Dog then adds its own self.breed afterward, avoiding duplication of the name/sound assignment logic. Dog.speak is an override: it has the same name and signature as Animal.speak, but a completely different body, and Python resolves rex.speak() to Dog.speak because Dog is the more specific (derived) type. Notice Dog.speak calls super().speak() internally, so it extends rather than fully discards the parent's behavior. describe() is not overridden in Dog, so rex.describe() falls back to Animal.describe, demonstrating inherited (unchanged) behavior. Finally, this example could not demonstrate method overloading, because Python does not support it: defining speak twice in the same class with different parameters would simply mean the later definition silently replaces the earlier one, not that Python dispatches based on argument count or type.
Cricket analogy: Virat Kohli's technique inherits from general batting fundamentals but overrides the follow-through with his own signature style; when commentators call for 'technique', the more specific Kohli style is what's used, not the generic textbook version, and his unchanged running-between-wickets habit falls back to the general coaching manual.
Key Takeaways
- Single inheritance means a subclass derives from exactly one direct parent class.
super().__init__()calls the parent's constructor so the subclass can reuse its initialization logic.- Method overriding replaces a parent's method implementation in the subclass;
super().method()can still invoke the parent's version. - Python does not support true method overloading — defining the same method name twice in one class just overwrites the first definition.
Practice what you learned
1. What does `super().__init__(name, sound="Woof")` do inside `Dog.__init__`?
2. What is method overriding?
3. Does Python support true method overloading (same method name, different parameter signatures, within one class)?
4. In the example, why does `rex.describe()` return the same output style as it would for a plain `Animal`?
Was this page helpful?
You May Also Like
OOP Core Concepts
An introduction to the four pillars of object-oriented programming: encapsulation, abstraction, inheritance, and polymorphism.
Classes and Objects
How classes act as blueprints for objects, and the difference between class attributes and instance attributes.
Polymorphism and Abstraction
Distinguishing polymorphism (same interface, different implementations) from abstraction (hiding implementation details) using Python's abc module.
Liskov Substitution and Interface Segregation
Understand why subtypes must honor their base type's contract and why fat interfaces should be split into focused ones.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics