BeSmart Computer Education Logo
BeSmart Computer Education Modern Computer Coaching in Haldwani
Call for Offline Batches

Python OOP Notes

Object-Oriented Programming (OOP) — What & Why with Examples

1) OOP Overview

What

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.

Why

Large projects me code ko organize, reuse & maintain karna easy hota hai — abstraction, encapsulation, inheritance & polymorphism ke through.

4 pillars: Encapsulation, Abstraction, Inheritance, Polymorphism.

2) Class & Object

What

Class blueprint hoti hai; Object us blueprint ka real instance hota hai.

Why

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

What

__init__ object create hote hi run hota hai; self current object ko refer karta hai.

Why

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

What

Instance methods me self, class methods me @classmethod & cls, static methods me na self na cls.

Why

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

What

Data + methods ko ek unit me bandhna; Python me privacy conventions: name (public), _name (protected), __name (private).

Why

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

What

Unnecessary details hide karke sirf essential interface expose karna. Abstract base classes se contracts define karte hain.

Why

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

What

Existing class (parent) ki properties/methods ko child class inherit karke reuse/extend karta hai. Types: single, multilevel, multiple.

Why

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
MRO: Multiple inheritance me method search order = class.__mro__ sequence.

8) Polymorphism

What

Same interface, different implementations (method overriding); Python me duck typing bhi common.

Why

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

What

Composition = has-a relation (Car has Engine). Inheritance = is-a relation (Student is a Person).

Why

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

What

Special methods: __repr__, __str__, __len__, __iter__, __eq__, __add__, etc.

Why

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

What

@dataclass boilerplate (__init__, __repr__, __eq__) auto-generate karta hai for data models.

Why

Faster development, less code, cleaner models.

from dataclasses import dataclass
@dataclass
class Course:
    title: str
    weeks: int
    fees: float = 0.0

12) Type Hints

What

Optional annotations for variables/params/returns (typing module).

Why

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)

  • self miss — 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)

  1. Define class, object, attribute, method with a real-world example.
  2. Create a Calculator class with add/sub/mul/div (handle divide by zero).
  3. Predict output:
    class A:
        x = 10
        def __init__(self): self.x = 20
    a = A()
    print(A.x, a.x)
  4. Design Temperature with celsius property; prevent < -273.15.
  5. Make abstract Vehicle with max_speed(); implement Bike/Car and iterate polymorphically.
  6. Build multilevel Person -> Teacher -> HeadTeacher with role() overrides using super().
  7. Write log(obj) that uses duck typing: if write() exists, accept; else reject.
  8. Implement Money with currency+amount and __add__ validating same currency.
  9. Multiple inheritance MRO demo; print Z.__mro__ and explain.
  10. Library design: choose composition vs inheritance; justify with pseudo-code.

Leave a Comment