Table of Contents
Python Objects, Classes, Inheritance, Polymorphism, and Operator Overloading
Welcome to your beginner-friendly guide to Python’s object-oriented programming! This tutorial will help you understand the essential concepts of classes, objects, inheritance, polymorphism, and operator overloading in Python. You’ll learn step-by-step with practical examples, clear explanations, and tips to avoid common mistakes.
Learning Goals
- Understand what classes and objects are in Python
- Learn how to define and use classes and objects
- Explore inheritance and how it enables code reuse
- Master polymorphism and see how it makes code flexible
- Discover operator overloading and how to customize operators for your own classes
- Get practical tips and learn to avoid common mistakes
Introduction to Classes and Objects
Python is an object-oriented language, which means it allows you to organize code using classes and objects. A class is a blueprint for creating objects. An object is an instance of a class, containing data (attributes) and functions (methods) that operate on that data.
Think of a class as a blueprint for a house. You can build many houses (objects) from the same blueprint (class).
Defining a Class
To define a class in Python, use the class keyword:
class Bike:
name = ""
gear = 0
Here, Bike is the class name, and name and gear are attributes with default values.
Creating Objects
To create an object (instance) of a class, use the class name followed by parentheses:
bike1 = Bike()
Now, bike1 is an object of the Bike class. You can access and modify its attributes using dot notation:
bike1.name = "Mountain Bike"
bike1.gear = 11
print(f"Name: {bike1.name}, Gears: {bike1.gear}")
Output:
Name: Mountain Bike, Gears: 11
Multiple Objects from a Class
You can create multiple objects from the same class, each with its own data:
class Employee:
employeeID = 0
employee1 = Employee()
employee2 = Employee()
employee1.employeeID = 1001
employee2.employeeID = 1002
print(f"Employee ID: {employee1.employeeID}")
print(f"Employee ID: {employee2.employeeID}")
Output:
Employee ID: 1001
Employee ID: 1002
Methods and Constructors
A method is a function defined inside a class. The constructor is a special method called __init__ that initializes the object’s attributes when it is created.
class Bike:
def __init__(self, name=""):
self.name = name
bike1 = Bike("Mountain Bike")
print(bike1.name)
Output:
Mountain Bike
The self parameter refers to the current object. It is used to access attributes and methods within the class.
Inheritance: Reusing and Extending Code
Inheritance allows a class (child/subclass) to inherit attributes and methods from another class (parent/superclass). This promotes code reuse and makes your code easier to maintain.
class Animal:
name = ""
def eat(self):
print("I can eat")
class Dog(Animal):
def display(self):
print("My name is", self.name)
labrador = Dog()
labrador.name = "Rohu"
labrador.eat()
labrador.display()
Output:
I can eat
My name is Rohu
Inheritance represents an “is-a” relationship. For example, a Dog is a Animal.
Types of Inheritance
| Type | Description |
|---|---|
| Single Inheritance | Child class inherits from one parent class |
| Multiple Inheritance | Child class inherits from multiple parent classes |
| Multilevel Inheritance | Child class inherits from a parent, which itself inherits from another parent |
| Hierarchical Inheritance | Multiple child classes inherit from a single parent class |
| Hybrid Inheritance | Combination of multiple types of inheritance |
Method Overriding and the super() Function
If a child class defines a method with the same name as its parent, it overrides the parent method. You can use super() to call the parent method from the child.
class Animal:
def eat(self):
print("I can eat")
class Dog(Animal):
def eat(self):
super().eat()
print("I like to eat bones")
labrador = Dog()
labrador.eat()
Output:
I can eat
I like to eat bones
Polymorphism: One Interface, Many Forms
Polymorphism means “many forms.” In Python, it allows you to use the same method or operator for different types of objects, making your code flexible and reusable.
Polymorphism with Built-in Operators
| Operator | Example | Result |
|---|---|---|
| + | 1 + 2 | 3 (addition) |
| + | “Hello” + “World” | HelloWorld (concatenation) |
Polymorphism in Class Methods
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(f"I am a cat. My name is {self.name}. I am {self.age} years old.")
def make_sound(self):
print("Meow")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(f"I am a dog. My name is {self.name}. I am {self.age} years old.")
def make_sound(self):
print("Bark")
cat1 = Cat("Kitty", 2.5)
dog1 = Dog("Fluffy", 4)
for animal in (cat1, dog1):
animal.make_sound()
animal.info()
Output:
Meow
I am a cat. My name is Kitty. I am 2.5 years old.
Bark
I am a dog. My name is Fluffy. I am 4 years old.
Both classes have info() and make_sound() methods. You can call these methods on any object, regardless of its class, thanks to polymorphism.
Polymorphism and Inheritance
Child classes can override parent methods, and you can use a common interface to access specialized behavior. This is called method overriding.
from math import pi
class Shape:
def __init__(self, name):
self.name = name
def area(self):
pass
def fact(self):
return "I am a two-dimensional shape."
def __str__(self):
return self.name
class Square(Shape):
def __init__(self, length):
super().__init__("Square")
self.length = length
def area(self):
return self.length ** 2
def fact(self):
return "Squares have each angle equal to 90 degrees."
class Circle(Shape):
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius
def area(self):
return pi * self.radius ** 2
a = Square(4)
b = Circle(7)
print(b)
print(b.fact())
print(a.fact())
print(b.area())
Output:
Circle
I am a two-dimensional shape.
Squares have each angle equal to 90 degrees.
153.93804002589985
Polymorphism lets you use a common interface (fact(), area()) for different shapes, and Python automatically calls the correct method for each object.
Operator Overloading: Customizing Operators for Your Classes
Operator overloading lets you define how operators like +, -, *, etc., behave for your own classes. This is done by implementing special methods (like __add__, __sub__, etc.) in your class.
Example: Adding Two Points
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y)
p1 = Point(1, 2)
p2 = Point(2, 3)
p3 = p1 + p2 # Calls the __add__() method
print((p3.x, p3.y))
Output:
(3, 5)
Here, p1 + p2 calls the __add__ method, allowing you to use the + operator with your custom class.
Common Operator Overloading Methods
| Operator | Expression | Special Method |
|---|---|---|
| Addition | p1 + p2 | p1.__add__(p2) |
| Subtraction | p1 – p2 | p1.__sub__(p2) |
| Multiplication | p1 * p2 | p1.__mul__(p2) |
| Division | p1 / p2 | p1.__truediv__(p2) |
| Comparison | p1 < p2 | p1.__lt__(p2) |
| Equality | p1 == p2 | p1.__eq__(p2) |
Example: Overloading Comparison Operators
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __lt__(self, other):
return self.age < other.age
p1 = Person("Alice", 20)
p2 = Person("Bob", 30)
print(p1 < p2) # True
print(p2 < p1) # False
Output:
True
False
Operator overloading makes your classes behave like built-in types, improving code readability and flexibility.
Practical Tips and Common Mistakes
| Common Mistake | Correct Usage |
|---|---|
Forgetting self in method definitions | Always include self as the first parameter |
Misusing operator overloading (e.g., using + for subtraction) | Use operators for their intended purpose |
Not using super() when extending parent methods | Use super() to call parent methods |
| Not overriding methods in child classes | Override methods to customize behavior |
Summary and Next Steps
Congratulations! You now understand the basics of Python's object-oriented programming: classes, objects, inheritance, polymorphism, and operator overloading. These concepts help you write clean, reusable, and flexible code.
- Practice by creating your own classes and objects
- Experiment with inheritance and method overriding
- Try operator overloading for custom classes
- Explore more advanced OOP topics like encapsulation and inner classes
Continue your learning journey on skillplayground with more tutorials, exercises, and coding challenges!
