Python OOPs Concept

Python Tutorial

Table of Contents

Beginner-Friendly Python Tutorial: Objects, Classes, Inheritance, Polymorphism, and Operator Overloading

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

TypeDescription
Single InheritanceChild class inherits from one parent class
Multiple InheritanceChild class inherits from multiple parent classes
Multilevel InheritanceChild class inherits from a parent, which itself inherits from another parent
Hierarchical InheritanceMultiple child classes inherit from a single parent class
Hybrid InheritanceCombination 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

OperatorExampleResult
+1 + 23 (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

OperatorExpressionSpecial Method
Additionp1 + p2p1.__add__(p2)
Subtractionp1 – p2p1.__sub__(p2)
Multiplicationp1 * p2p1.__mul__(p2)
Divisionp1 / p2p1.__truediv__(p2)
Comparisonp1 < p2p1.__lt__(p2)
Equalityp1 == p2p1.__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 MistakeCorrect Usage
Forgetting self in method definitionsAlways 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 methodsUse super() to call parent methods
Not overriding methods in child classesOverride 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!

Scroll to Top