Object-Oriented Programming (OOP) is one of the most important paradigms in modern software development. Python, being a versatile and powerful programming language, fully supports OOP principles, allowing developers to design reusable, scalable, and efficient programs.
In this post, we will explore Object-Oriented Programming in Python in great detail — including concepts like classes, objects, inheritance, polymorphism, and encapsulation. We will go step-by-step through each concept, with explanations and examples that will help you understand how OOP works in Python.
What is Object-Oriented Programming?
Object-Oriented Programming is a programming paradigm that organizes software design around objects rather than functions or logic.
An object represents a real-world entity that has both attributes (data) and behaviors (methods).
The key idea behind OOP is to model your code in a way that mirrors how things exist and behave in the real world.
For example:
- A Car can be modeled as a class.
- The color, model, and speed can be its attributes.
- The drive() and brake() actions can be its methods.
Advantages of OOP
Object-Oriented Programming offers several key advantages:
- Modularity – Code is organized into classes and objects, making it easier to maintain and understand.
- Reusability – Classes can be reused across multiple projects or modules.
- Extensibility – You can easily extend existing classes without modifying them.
- Scalability – OOP makes it easier to manage large applications.
- Encapsulation – Keeps data secure by restricting direct access.
- Polymorphism – Allows one interface to be used for different data types.
Classes and Objects
What is a Class?
A class is a blueprint for creating objects. It defines the properties (attributes) and behaviors (methods) that its objects will have.
For example:
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def start_engine(self):
print(f"{self.brand} {self.model}'s engine has started.")
Here,
Car
is a class.brand
andmodel
are attributes.start_engine()
is a method that defines the car’s behavior.
What is an Object?
An object is an instance of a class. It represents a specific entity that has the data and behavior defined by the class.
Example:
car1 = Car("Toyota", "Camry")
car2 = Car("Honda", "Civic")
car1.start_engine()
car2.start_engine()
Output:
Toyota Camry's engine has started.
Honda Civic's engine has started.
Each object (car1
, car2
) has its own data (brand and model) and can perform actions (methods).
The __init__
Method
The __init__
method is a special method in Python that is automatically called when an object is created. It is used to initialize the object’s attributes.
Example:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
student1 = Student("Alice", 20)
print(student1.name)
print(student1.age)
Output:
Alice
20
The self
keyword refers to the instance of the class, allowing you to access or modify its attributes.
Instance Variables and Class Variables
In Python, you can have two types of variables in a class:
Instance Variables
These are variables that are unique to each instance (object) of a class.
class Dog:
def __init__(self, name):
self.name = name
Each Dog
object has its own name
attribute.
Class Variables
These are shared across all instances of a class.
class Dog:
species = "Canine"
def __init__(self, name):
self.name = name
dog1 = Dog("Rex")
dog2 = Dog("Buddy")
print(dog1.species)
print(dog2.species)
Output:
Canine
Canine
Methods in Classes
Methods are functions defined inside a class that describe the behaviors of an object.
Example:
class Calculator:
def add(self, a, b):
return a + b
calc = Calculator()
print(calc.add(10, 5))
Output:
15
You can define multiple methods inside a class to represent different behaviors.
The self
Keyword
The self
keyword represents the instance of the class and allows you to access its attributes and methods.
For example:
class Person:
def __init__(self, name):
self.name = name
def greet(self):
print(f"Hello, my name is {self.name}")
When you create an object, Python automatically passes the object itself as the first argument to the method.
Encapsulation
Encapsulation is one of the core principles of OOP. It means restricting access to certain details of an object and only exposing what is necessary.
It helps in:
- Protecting the data from accidental modification.
- Maintaining data integrity.
Example of Encapsulation
class BankAccount:
def __init__(self, balance):
self.__balance = balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
else:
print("Invalid deposit amount")
def get_balance(self):
return self.__balance
account = BankAccount(1000)
account.deposit(500)
print(account.get_balance())
Output:
1500
Here, __balance
is a private variable. It cannot be accessed directly outside the class.
Attempting to access it will cause an error:
print(account.__balance) # AttributeError
Encapsulation ensures that sensitive data remains safe.
Inheritance
Inheritance allows a class to inherit attributes and methods from another class.
This helps in reusing code and creating a logical hierarchy between classes.
Example:
class Animal:
def speak(self):
print("Animal is speaking")
class Dog(Animal):
def bark(self):
print("Dog is barking")
dog = Dog()
dog.speak()
dog.bark()
Output:
Animal is speaking
Dog is barking
Here, Dog
inherits from Animal
. This means the Dog
class can use methods defined in the Animal
class.
The super()
Function
super()
is used to call methods from the parent class.
Example:
class Person:
def __init__(self, name):
self.name = name
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name)
self.salary = salary
Here, the super()
function initializes the parent class attributes, ensuring both parent and child attributes are set properly.
Types of Inheritance in Python
- Single Inheritance – One child class inherits from one parent class.
- Multiple Inheritance – One child class inherits from multiple parent classes.
- Multilevel Inheritance – A chain of inheritance (A → B → C).
- Hierarchical Inheritance – Multiple child classes inherit from one parent class.
- Hybrid Inheritance – A combination of the above types.
Example of Multiple Inheritance:
class Father:
def skills(self):
print("Gardening, Programming")
class Mother:
def skills(self):
print("Cooking, Painting")
class Child(Father, Mother):
def skills(self):
super().skills()
print("Dancing, Singing")
child = Child()
child.skills()
Output:
Gardening, Programming
Dancing, Singing
Polymorphism
Polymorphism means many forms. In OOP, it allows objects of different classes to be treated as objects of a common base class.
It enables the same method to behave differently depending on the object that calls it.
Example of Polymorphism with Inheritance
class Bird:
def speak(self):
print("Bird is making a sound")
class Parrot(Bird):
def speak(self):
print("Parrot says hello")
class Crow(Bird):
def speak(self):
print("Crow says caw")
for bird in [Parrot(), Crow()]:
bird.speak()
Output:
Parrot says hello
Crow says caw
Here, the same method name speak()
behaves differently depending on the object type.
Polymorphism with Functions
You can also use polymorphism with functions that accept objects of different types.
Example:
class Cat:
def sound(self):
return "Meow"
class Dog:
def sound(self):
return "Bark"
def animal_sound(animal):
print(animal.sound())
cat = Cat()
dog = Dog()
animal_sound(cat)
animal_sound(dog)
Output:
Meow
Bark
This demonstrates how polymorphism allows different classes to implement the same method with different behavior.
Abstraction
Abstraction means hiding unnecessary details and exposing only the essential features.
In Python, abstraction can be achieved using abstract classes and abstract methods from the abc
module.
Example:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius * self.radius
circle = Circle(5)
print(circle.area())
Output:
78.5
Here,
Shape
is an abstract class.area()
is an abstract method that must be implemented in any subclass.
Composition
Composition is another important concept in OOP where one class is composed of one or more objects of other classes.
It represents a “has-a” relationship.
Example:
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self):
self.engine = Engine() # Composition
def start(self):
self.engine.start()
print("Car is running")
car = Car()
car.start()
Output:
Engine started
Car is running
This example shows that a car has an engine, demonstrating composition.
Magic Methods in OOP
Python classes have special methods called magic methods or dunder methods (double underscore).
Example:
__init__()
– Initializes an object.__str__()
– Returns a string representation of an object.__add__()
– Defines behavior for the+
operator.
Example of __str__
and __add__
class Number:
def __init__(self, value):
self.value = value
def __add__(self, other):
return self.value + other.value
def __str__(self):
return f"Number({self.value})"
num1 = Number(10)
num2 = Number(20)
print(num1 + num2)
print(num1)
Output:
30
Number(10)
Magic methods allow you to define how your objects behave with operators and built-in functions.
Real-Life Example of OOP in Python
Let’s create a simple simulation of a Library Management System using OOP principles.
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
self.is_available = True
def borrow(self):
if self.is_available:
self.is_available = False
print(f"{self.title} has been borrowed.")
else:
print(f"{self.title} is not available.")
def return_book(self):
self.is_available = True
print(f"{self.title} has been returned.")
class Library:
def __init__(self):
self.books = []
def add_book(self, book):
self.books.append(book)
def show_books(self):
for book in self.books:
status = "Available" if book.is_available else "Borrowed"
print(f"{book.title} by {book.author} - {status}")
book1 = Book("1984", "George Orwell")
book2 = Book("Pride and Prejudice", "Jane Austen")
library = Library()
library.add_book(book1)
library.add_book(book2)
library.show_books()
book1.borrow()
library.show_books()
Output:
1984 by George Orwell - Available
Pride and Prejudice by Jane Austen - Available
1984 has been borrowed.
1984 by George Orwell - Borrowed
Pride and Prejudice by Jane Austen - Available
This example shows how OOP concepts like encapsulation, abstraction, and composition come together to create a functional program.
Leave a Reply