Object-Oriented Programming (OOP) in Python
🔴 Advanced
📖 Definition
Object-Oriented Programming (OOP) is a paradigm that structures software around Classes (blueprints) and Objects (instances created from blueprints). OOP encapsulates state (data attributes) and behavior (methods) into reusable objects, supporting Encapsulation, Inheritance, and Polymorphism.
🇮🇳 Hindi
OOP mein Class ek design/blueprint hoti hai aur Object us design se bane actual instances hote hain. Instance variables initialize karne ke liye __init__() constructor method ka use hota hai, aur self parameter current object instance ko point karta hai.
🚩 Marathi
Class mhanje blueprint aani Object mhanje instance. Objects create honyasathi __init__() constructor vaparatat, aani self current instance la point karto.
🤔 Why Do We Use It?
Procedural programming keeps data variables and functions separated, leading to fragmented code as applications grow. OOP packages data and functions together into self-contained objects, reflecting real-world entities.
🧠 Simple Explanation
Think of a Class as a factory architectural blueprint for a smartphone. The blueprint defines attributes (model, storage, battery_level) and methods (make_call(), charge()). An Object is the actual physical phone manufactured from that blueprint.
📝 1. The __init__ Constructor & self Parameter
__init__(self, ...): Automatically invoked when an object instance is created withnew_obj = ClassName().self: Explicit parameter representing the current instance of the object (must be the first parameter in instance methods!).
class BankAccount:
# Constructor
def __init__(self, owner, balance=0.0):
self.owner = owner # Instance attribute
self.balance = balance # Instance attribute
# Instance Method
def deposit(self, amount):
if amount > 0:
self.balance += amount
print(f"Deposited ₹{amount:.2f}. New Balance: ₹{self.balance:.2f}")
📝 2. Class Attributes vs Instance Attributes
- Instance Attributes (
self.attr): Unique to each individual object instance. - Class Attributes: Defined directly in class body; shared globally across ALL object instances!
class Student:
school_name = "Delhi Public School" # Class attribute (shared)
def __init__(self, name):
self.name = name # Instance attribute (unique)
📝 3. Inheritance (super()) & Encapsulation Conventions
- Inheritance:
class SubClass(ParentClass):inherits parent methods. super().__init__(): Calls parent class constructor.- Protected Convention (
_attr): Single underscore signals internal use. - Private Name Mangling (
__attr): Double underscore mangles name to prevent external access.
💡 Complete Example: E-Commerce Product & Electronics Subclass
# OOP E-Commerce System
class Product:
"""Parent Superclass representing general store items."""
def __init__(self, product_id, name, price):
self.product_id = product_id
self.name = name
self._price = max(0.0, price) # Protected attribute
def get_price(self):
return self._price
def display_details(self):
return f"[{self.product_id}] {self.name} - ₹{self._price:.2f}"
# Subclass Inheriting from Product
class ElectronicsProduct(Product):
"""Subclass adding warranty attributes and method overriding."""
def __init__(self, product_id, name, price, warranty_months):
# Calling parent constructor using super()
super().__init__(product_id, name, price)
self.warranty_months = warranty_months
# Overriding Parent Method (Polymorphism)
def display_details(self):
base_details = super().display_details()
return f"{base_details} | Warranty: {self.warranty_months} Months"
# Testing OOP Classes
if __name__ == "__main__":
p1 = Product("P-101", "Coffee Mug", 350.00)
p2 = ElectronicsProduct("E-201", "Gaming Mouse", 1800.00, 24)
print("=== E-COMMERCE PRODUCT CATALOG ===")
print(p1.display_details())
print(p2.display_details())
👀 Output
=== E-COMMERCE PRODUCT CATALOG ===
[P-101] Coffee Mug - ₹350.00
[E-201] Gaming Mouse - ₹1800.00 | Warranty: 24 Months
⚠️ Common Mistakes
- Forgetting to include
selfas the first parameter in instance methods (def my_method():causesTypeError: my_method() takes 0 positional arguments but 1 was givenwhen called on an instance!). - Modifying a class attribute on an instance (
instance.class_attr = val), which creates a new instance attribute instead of updating the shared class variable!
🛡️ Safety / Important Notes
Python relies on Duck Typing (“If it walks like a duck and quacks like a duck, it’s a duck”). Polymorphism in Python does not require strict interface inheritance—any object that provides the required method name can be used polymorphically.
🌍 Real-World Usage
Django database models, custom exception classes, UI widget hierarchies, API response wrappers, and machine learning pipelines.
🧪 Try It Yourself
- Create a
Carclass with attributesbrandandmodel, and a methoddrive(). - Instantiate two distinct
Carobjects and invokedrive()on both.
🎯 Mini Challenge
Create a BankAccount class with private attribute __balance, and provide deposit(amount), withdraw(amount), and get_balance() methods with input validation.
🔗 Related Topics
🧭 Navigation
| ← Python Home | ← Previous: Exception Handling | Next: Iterators and Generators → |