Object-Oriented Programming (OOP) — What & Why with Examples
1) OOP Overview
OOP ek programming style hai jisme real-world entities (Student, BankAccount) ko objects ke form me represent karte hain, jo data (attributes) & behavior (methods) ko ek saath hold karte hain.
Large projects me code ko organize, reuse & maintain karna easy hota hai — abstraction, encapsulation, inheritance & polymorphism ke through.
2) Class & Object
Class blueprint hoti hai; Object us blueprint ka real instance hota hai.
Blueprint se aap multiple objects bana sakte ho with consistent structure; reusability & clarity improve hoti hai.
class Student:
school = "BeSmart Computer Education" # class variable (shared)
def __init__(self, name, cls):
self.name = name # instance variable
self.cls = cls
def intro(self):
print(f"Hi, I'm {self.name} from class {self.cls} at {Student.school}")
s1 = Student("Aarav", 12)
s1.intro()
3) Constructor __init__ & self
__init__ object create hote hi run hota hai; self current object ko refer karta hai.
Initialization centralize hota hai (defaults/validations); self se instance data/methods access karte hain.
class Point:
def __init__(self, x=0, y=0):
self.x, self.y = x, y
4) Methods: Instance, Class, Static
Instance methods me self, class methods me @classmethod & cls, static methods me na self na cls.
Different contexts: object-specific logic, class-level configuration/alternate constructors, utility helpers.
class MathOps:
pi = 3.14159
def __init__(self, r): self.r = r
def area(self): return MathOps.pi * (self.r ** 2)
@classmethod
def change_pi(cls, new_pi): cls.pi = new_pi
@staticmethod
def square(x): return x * x
5) Encapsulation
Data + methods ko ek unit me bandhna; Python me privacy conventions: name (public), _name (protected), __name (private).
Data safety & controlled access; validation via properties; internal details ko hide karke clean API.
class BankAccount:
def __init__(self, holder, balance=0):
self.holder = holder
self.__balance = balance
@property
def balance(self): return self.__balance
@balance.setter
def balance(self, amt):
if amt < 0: raise ValueError("Negative not allowed")
self.__balance = amt
6) Abstraction
Unnecessary details hide karke sirf essential interface expose karna. Abstract base classes se contracts define karte hain.
Complexity kam; interchangeable implementations; testability & team collaboration better.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self): ...
class Rectangle(Shape):
def __init__(self, w, h): self.w, self.h = w, h
def area(self): return self.w * self.h
7) Inheritance
Existing class (parent) ki properties/methods ko child class inherit karke reuse/extend karta hai. Types: single, multilevel, multiple.
Code reuse & specialization. super() se parent behavior extend/override safely.
class Person:
def __init__(self, name): self.name = name
class Student(Person):
def __init__(self, name, roll):
super().__init__(name); self.roll = roll
class.__mro__ sequence.8) Polymorphism
Same interface, different implementations (method overriding); Python me duck typing bhi common.
Extensibility — naye classes add ho sakte without changing client code.
class Dog: def speak(self): return "Woof"
class Cat: def speak(self): return "Meow"
def announce(animal): print(animal.speak())
9) Composition vs Inheritance
Composition = has-a relation (Car has Engine). Inheritance = is-a relation (Student is a Person).
Composition flexible & less coupling; inheritance ka overuse brittle design create karta hai.
class Engine:
def start(self): print("start")
class Car:
def __init__(self): self.engine = Engine()
def drive(self): self.engine.start()
10) Dunder (Magic) Methods
Special methods: __repr__, __str__, __len__, __iter__, __eq__, __add__, etc.
Pythonic behavior — objects natural tarike se print/compare/iterate ho sakte.
class Vector2D:
def __init__(self, x, y): self.x, self.y = x, y
def __repr__(self): return f"Vector2D({self.x}, {self.y})"
def __add__(self, o): return Vector2D(self.x+o.x, self.y+o.y)
11) Dataclasses
@dataclass boilerplate (__init__, __repr__, __eq__) auto-generate karta hai for data models.
Faster development, less code, cleaner models.
from dataclasses import dataclass
@dataclass
class Course:
title: str
weeks: int
fees: float = 0.0
12) Type Hints
Optional annotations for variables/params/returns (typing module).
Readability, editor autocompletion, static analysis tools (mypy), fewer bugs.
from typing import List
class Batch:
def __init__(self, students: List[str]): self.students = students
def add(self, name: str) -> None: self.students.append(name)
13) Mini Programs
Student Average
class Student:
school = "BeSmart Computer Education"
def __init__(self, name, marks): self.name, self.marks = name, marks
def average(self): return sum(self.marks)/len(self.marks)
print(Student("Kabir",[80,92,76]).average())
Shapes (Abstraction + Polymorphism)
from abc import ABC, abstractmethod
import math
class Shape(ABC):
@abstractmethod
def area(self): ...
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return math.pi * self.r * self.r
class Square(Shape):
def __init__(self, a): self.a = a
def area(self): return self.a * self.a
Library (Composition)
class Book:
def __init__(self, title, author): self.title, self.author = title, author
class Library:
def __init__(self): self.catalog = []
def add_book(self, book): self.catalog.append(book)
def list_titles(self): return [b.title for b in self.catalog]
14) Common Pitfalls (Why they matter)
selfmiss — method instance context lose karta hai; errors.- Mutable class variables — shared state bugs (e.g., list/dict).
- Over-inheritance — tight coupling; composition often better.
- Assuming overloading — Python doesn’t support by signature; use defaults/dispatcher.
- Ignoring MRO — unexpected method selection in multiple inheritance.
15) Practice Questions (Easy → Hard)
- Define class, object, attribute, method with a real-world example.
- Create a
Calculatorclass with add/sub/mul/div (handle divide by zero). - Predict output:
class A: x = 10 def __init__(self): self.x = 20 a = A() print(A.x, a.x) - Design
Temperaturewithcelsiusproperty; prevent < -273.15. - Make abstract
Vehiclewithmax_speed(); implementBike/Carand iterate polymorphically. - Build multilevel
Person -> Teacher -> HeadTeacherwithrole()overrides usingsuper(). - Write
log(obj)that uses duck typing: ifwrite()exists, accept; else reject. - Implement
Moneywith currency+amount and__add__validating same currency. - Multiple inheritance MRO demo; print
Z.__mro__and explain. - Library design: choose composition vs inheritance; justify with pseudo-code.