Object-Oriented Programming (OOP) in Python is a programming paradigm based on the concept of objects, which bundle data (attributes) and behavior (methods). Python supports OOP fully and makes it simple and flexible.
🧩 Core Concepts of OOP
1. Class
A class is a blueprint for creating objects.
class Car:
pass
2. Object
An object is an instance of a class.
my_car = Car()
3. Attributes
Variables that belong to a class or object.
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
4. Methods
Functions inside a class that describe behaviors.
class Car:
def start_engine(self):
print("Engine started!")
5. The __init__ Constructor
Called automatically when an object is created.
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
6. Encapsulation
Restricting direct access to data. Python uses naming conventions:
_protected_attribute__private_attribute
class Person:
def __init__(self, name):
self.__name = name # private
def get_name(self):
return self.__name
7. Inheritance
A class can inherit properties and methods from another class.
class Animal:
def sound(self):
print("Some sound")
class Dog(Animal):
def sound(self):
print("Bark!")
8. Polymorphism
Same method name, different behaviors.
for animal in [Dog(), Animal()]:
animal.sound() # Different outputs
9. Abstraction
Hiding complex details using abstract classes (via abc module).
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
✔️ Complete Example
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def drive(self):
print(f"The {self.color} {self.brand} is driving.")
class ElectricCar(Car):
def __init__(self, brand, color, battery_capacity):
super().__init__(brand, color)
self.battery_capacity = battery_capacity
def drive(self):
print(f"The electric {self.color} {self.brand} is silently driving.")
tesla = ElectricCar("Tesla", "red", 100)
tesla.drive()
🎯 Why Use OOP?
- Code reusability
- Modularity
- Easier maintenance
- Real-world modeling
Great — let’s go deeper into Object-Oriented Programming in Python with more advanced concepts, examples, diagrams, and best practices.
🔥 1. Class vs Instance Attributes
Instance Attributes
Unique to each object.
class Student:
def __init__(self, name):
self.name = name # instance attribute
Class Attributes
Shared across all instances.
class Student:
school = "Greenwood High" # class attribute
def __init__(self, name):
self.name = name
s1 = Student("Alice")
s2 = Student("Bob")
print(s1.school) # Greenwood High
print(s2.school) # Greenwood High
🔥 2. Method Types
✅ Instance Method
Most common — works on object attributes.
def study(self):
print(self.name, "is studying")
✅ Class Method
Uses @classmethod and cls.
class Person:
count = 0
def __init__(self):
Person.count += 1
@classmethod
def how_many(cls):
return cls.count
✅ Static Method
No self or cls — utility functions.
class Math:
@staticmethod
def add(a, b):
return a + b
🔥 3. Inheritance (Single, Multi-level, Multiple)
Single Inheritance
class A:
pass
class B(A):
pass
Multi-level Inheritance
class A:
pass
class B(A):
pass
class C(B):
pass
Multiple Inheritance
class A:
pass
class B:
pass
class C(A, B):
pass
Python solves method conflicts using MRO (Method Resolution Order).
🔥 4. Super() and Method Overriding
Using super()
class Parent:
def show(self):
print("Parent")
class Child(Parent):
def show(self):
super().show() # call Parent show()
print("Child")
🔥 5. Polymorphism with Duck Typing
Python doesn’t require explicit interfaces.
class Cat:
def sound(self):
print("Meow")
class Dog:
def sound(self):
print("Bark")
def make_sound(animal):
animal.sound()
make_sound(Dog())
make_sound(Cat())
🔥 6. Operator Overloading (Dunder Methods)
Python allows custom behavior for built-in operators:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
v1 = Vector(1, 3)
v2 = Vector(4, 2)
v3 = v1 + v2
print(v3.x, v3.y)
🔥 7. Properties (Getters and Setters)
Pythonic way to control attribute access.
class Person:
def __init__(self, age):
self._age = age
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if value < 0:
raise ValueError("Age cannot be negative")
self._age = value
🔥 8. Abstract Classes
Used to enforce methods in subclasses.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
🔥 9. Composition (HAS-A relationship)
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self):
self.engine = Engine() # Car HAS-A Engine
def start(self):
self.engine.start()
🔥 10. Best Practices for OOP in Python
| Principle | Description |
|---|---|
| SRP | Single Responsibility Principle |
| OCP | Open/Closed Principle |
| LSP | Liskov Substitution Principle |
| ISP | Interface Segregation |
| DIP | Dependency Inversion |
| Use properties | Avoid exposing raw attributes |
| Prefer composition over inheritance | More flexible |
🔥 11. Putting It All Together (Mini Project Example)
from abc import ABC, abstractmethod
class Account(ABC):
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
@abstractmethod
def withdraw(self, amount):
pass
def deposit(self, amount):
self.balance += amount
class SavingsAccount(Account):
def withdraw(self, amount):
if amount > self.balance:
print("Insufficient funds")
else:
self.balance -= amount
class Bank:
def __init__(self):
self.accounts = []
def add_account(self, acc):
self.accounts.append(acc)
bank = Bank()
acc1 = SavingsAccount("Alice", 500)
bank.add_account(acc1)
acc1.deposit(200)
acc1.withdraw(100)
print(acc1.balance)
If you want, I can continue with:
✅ Real-world OOP project
✅ UML diagrams
✅ OOP interview questions
✅ Exercises with solutions
✅ Advanced topics (mixins, metaclasses, decorators in OOP)
Just tell me “More” or specify what you want!

0 Comments