Python Inheritance and Polymorphism Explained
SkillVeris Team
Engineering Team

Inheritance lets a child class reuse and extend a parent class's attributes and methods, avoiding duplicated code.
In this guide, you'll learn:
- Polymorphism lets objects of different classes respond to the same method call in their own way, sharing one interface.
- Define inheritance by passing the parent class in parentheses: class Dog(Animal).
- super() calls the parent's methods, most commonly super().__init__() to reuse the parent's constructor.
- Method overriding lets a child replace a parent method, which is the mechanism behind polymorphism.
1Inheritance and Polymorphism Explained
Inheritance and polymorphism are two pillars of object-oriented programming in Python. Inheritance lets one class, the child, reuse and extend the attributes and methods of another, the parent, so shared code is written once. Polymorphism lets objects of different classes respond to the same method call in their own way.
The two work hand in hand. Inheritance builds a family of related classes that share common behavior, and polymorphism lets you treat all of them through a single, uniform interface — calling the same method name on each and getting the behavior appropriate to that object's type.
- class Animal:
- def speak(self): return '...'
- class Dog(Animal):
- def speak(self): return 'Woof'
- Dog().speak() # 'Woof' — overrides the parent
2How Inheritance Works
You create inheritance by naming the parent class in parentheses after the child class name. The child automatically gains all of the parent's methods and attributes, and can add new ones or replace existing ones. This models an 'is a' relationship — a Dog is an Animal.
- class Animal:
- def __init__(self, name): self.name = name
- def eat(self): return f'{self.name} is eating'
- class Cat(Animal): # Cat inherits from Animal
- def purr(self): return f'{self.name} purrs'
- c = Cat('Milo')
- print(c.eat()) # inherited: Milo is eating
- print(c.purr()) # new: Milo purrs
🔑Key Idea
Inheritance expresses an 'is a' relationship. Only use it when the child genuinely is a kind of the parent; otherwise prefer composition — holding an object as an attribute instead.
3Reusing Parent Code With super()
The super() function calls methods on the parent class from within the child. Its most common use is inside __init__, where super().__init__() runs the parent's constructor so you do not have to repeat its setup code before adding the child's own attributes.
- class Vehicle:
- def __init__(self, brand): self.brand = brand
- class ElectricCar(Vehicle):
- def __init__(self, brand, battery):
- super().__init__(brand) # run parent setup
- self.battery = battery
- e = ElectricCar('Tesla', 75)
- print(e.brand, e.battery) # Tesla 75
Why super() Matters
Calling super() keeps your code DRY and works correctly with multiple inheritance, where it follows Python's method resolution order. Hard-coding the parent name instead of using super() can break in more complex class hierarchies.
4Method Overriding
Method overriding is when a child class defines a method with the same name as one in the parent, replacing the parent's version for instances of the child. This is how a class customizes inherited behavior, and it is the mechanism that makes polymorphism possible.
- class Shape:
- def area(self): return 0
- class Circle(Shape):
- def __init__(self, r): self.r = r
- def area(self): return 3.14159 * self.r ** 2
- class Square(Shape):
- def __init__(self, s): self.s = s
- def area(self): return self.s ** 2
5Polymorphism in Action
Polymorphism means 'many forms': the same method call produces the right behavior for whatever object it acts on. Because each shape overrides area(), you can loop over a mixed list of shapes and call area() on each without knowing or caring about its exact type.
- shapes = [Circle(2), Square(3)]
- for shape in shapes:
- print(shape.area()) # 12.566... then 9
- # one interface, different implementations per object
💡Pro Tip
Polymorphism lets you write code against an interface, not a specific type. Adding a new shape later requires no change to the loop — it just needs its own area() method.
6Duck Typing in Python
Python takes polymorphism further with duck typing: 'if it walks like a duck and quacks like a duck, it is a duck.' An object does not need to inherit from a common base class to be used polymorphically — it only needs to have the method you call. Python checks for the behavior, not the type.
- class Duck: def sound(self): return 'Quack'
- class Person: def sound(self): return 'Hello'
- def make_sound(thing): return thing.sound()
- make_sound(Duck()) # Quack
- make_sound(Person()) # Hello — no shared base class needed
7Common Mistakes to Avoid
Inheritance is powerful but easy to misuse.
- Forgetting super().__init__() in the child, so the parent's attributes are never set.
- Overusing inheritance for code sharing when composition would model the relationship better.
- Building deep inheritance chains that become hard to follow — favor shallow hierarchies.
- Overriding a method but changing its signature, breaking the shared interface.
- Assuming polymorphism needs a common base class — duck typing only needs the right method.
- Using inheritance for a 'has a' relationship instead of the correct 'is a'.
⚠️Watch Out
Prefer composition over inheritance when a class merely needs another's functionality rather than being a kind of it. A Car has an Engine (composition); a Car is not an Engine (not inheritance).
8Key Takeaways
Inheritance and polymorphism together shape clean object-oriented design.
- Inheritance reuses and extends a parent class: class Child(Parent).
- super() calls parent methods, especially super().__init__().
- Overriding replaces a parent method in the child.
- Polymorphism lets different objects share one method interface.
- Duck typing means having the right method matters more than the type.
- Prefer composition when the relationship is 'has a', not 'is a'.
9Frequently Asked Questions
Q: What is the difference between inheritance and polymorphism? A: Inheritance is a class reusing and extending another class's code, forming a parent-child relationship. Polymorphism is different objects responding to the same method call in their own way. Inheritance builds the family; polymorphism lets you treat the family uniformly.
Q: What does super() do in Python? A: super() gives access to the parent class's methods from within a child. Its most common use is super().__init__() inside a child's constructor, which runs the parent's setup so you avoid duplicating it before adding the child's own attributes.
Q: What is method overriding? A: Overriding is defining a method in a child class with the same name as one in the parent, replacing the parent's version for that child's instances. It lets a subclass customize inherited behavior and is the core mechanism behind polymorphism.
Q: What is duck typing? A: Duck typing is Python's approach to polymorphism where an object's suitability is determined by whether it has the needed method, not by its class or inheritance. If an object has the method you call, it works — no shared base class is required.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Engineering Team
Our engineering writers turn abstract code concepts into hands-on, project-driven learning experiences.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.