Python OOP Concepts मराठीत – Class, Object, Inheritance, Polymorphism, Encapsulation आणि Abstraction

Python मध्ये सुरुवातीला Variables, Data Types, Conditions, Loops आणि Functions शिकल्यानंतर छोटे programs लिहिणं फारसं कठीण वाटत नाही. पण application थोडं मोठं झालं की एक वेगळी अडचण समोर येते.

समजा तुम्ही Student Management System बनवत आहात.

सुरुवातीला काही students साठी variables तयार करून काम भागू शकतं:

student1_name = "Amit"
student1_marks = 78

student2_name = "Sneha"
student2_marks = 85

पण students 10, 100 किंवा 10,000 झाले तर?

प्रत्येक student साठी वेगवेगळे variables आणि functions लिहिणं, त्यांचा data manage करणं आणि code maintain करणं अवघड होईल.

इथे Object-Oriented Programming म्हणजेच OOP उपयोगी पडतं.

OOP मध्ये आपण related data आणि त्या data वर काम करणारा logic एका structured unit मध्ये ठेवू शकतो. Python मध्ये class हा अशा प्रकारे data आणि functionality एकत्र organize करण्याचा मुख्य मार्ग आहे.

OOP म्हणजे Object-Oriented Programming.

सोप्या भाषेत सांगायचं तर, application मधील related data आणि behaviour यांना objects आणि classes च्या माध्यमातून व्यवस्थित organize करण्याची programming पद्धत म्हणजे OOP. उदाहरण म्हणून Student घेऊ.

एका student बद्दल आपल्याकडे:

Data:

  • नाव
  • roll number
  • marks
  • course

Behaviour:

  • marks update करणे
  • result calculate करणे
  • student ची माहिती दाखवणे

हे सगळं वेगवेगळ्या variables आणि functions मध्ये विखुरण्याऐवजी Student नावाच्या class मध्ये organize करता येतं.

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

    def result(self):
        if self.marks >= 35:
            return "Pass"
        return "Fail"

आता:

student1 = Student("Amit", 78)

print(student1.name)
print(student1.result())

Output:

Amit
Pass

इथे Student हा class आहे आणि student1 हा त्या class चा object आहे.

Class म्हणजे एखाद्या प्रकारच्या objects साठी structure आणि behaviour define करणारा template.

उदा:

class Student:
    pass

इथे आपण Student नावाचा class तयार केला.

Class स्वतः student ची actual information नाही. तो student object मध्ये कोणता data आणि कोणत्या methods असतील याची रचना define करतो.

थोडक्यात:

Class  → Structure / Design
Object → त्या class वरून तयार झालेली actual instance

एक practical example

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

    def show_result(self):
        if self.marks >= 35:
            print(f"{self.name} Pass आहे")
        else:
            print(f"{self.name} Fail आहे")

आता या class वरून अनेक objects तयार करू शकतो:

s1 = Student("Amit", 78)
s2 = Student("Sneha", 91)
s3 = Student("Rahul", 32)

तीनही objects चा structure समान आहे, पण त्यांच्यातील data वेगळा आहे.

Object म्हणजे class ची actual instance.

s1 = Student("Amit", 78)

इथे:

  • Student → Class
  • s1 → Object
  • "Amit" → Object चा data
  • 78 → Object चा data

एकाच class पासून अनेक objects तयार करता येतात.

s1 = Student("Amit", 78)
s2 = Student("Sneha", 91)

दोघांकडे name आणि marks आहेत, पण values वेगळ्या आहेत.

हेच OOP चं एक महत्त्वाचं advantage आहे.

OOP समजताना हे तीन शब्द उपयोगी पडतात.

1. State

Object मधील data म्हणजे त्याची state.

s1.name
s1.marks

2. Behaviour

Object काय काम करू शकतो ते त्याचं behaviour.

s1.show_result()

3. Identity

प्रत्येक object स्वतंत्र instance असतो.

s1 = Student("Amit", 78)
s2 = Student("Amit", 78)

दोघांचा data सारखा असला तरी s1 आणि s2 हे दोन वेगळे objects आहेत.

Python OOP शिकताना beginners ना सर्वात जास्त confusion देणाऱ्या गोष्टींपैकी एक म्हणजे self.

उदा:

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

इथे self म्हणजे ज्या object वर method चालत आहे तो current object.

समजा:

s1 = Student("Amit", 78)
s2 = Student("Sneha", 91)

जेव्हा:

s1.show_result()

चालतो, तेव्हा method s1 object च्या data वर काम करते.

आणि:

s2.show_result()

चालवल्यावर तीच method s2 च्या data वर काम करते. म्हणून self.name म्हणजे current object चं name.

एक common mistake

हे चुकीचं:

class Student:
    def __init__(name, marks):
        self.name = name

कारण instance method मध्ये current instance साठी पहिला parameter असतो.

योग्य:

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

एक महत्त्वाची गोष्ट: self हा Python मधला reserved keyword नाही; तो एक conventional parameter name आहे. पण instance methods मध्ये त्याच अर्थाने self वापरणं standard आणि readable पद्धत आहे.

__init__() ही special method आहे जी object तयार झाल्यानंतर त्याची initial state सेट करण्यासाठी वापरली जाते.

उदा.:

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

आता:

emp = Employee("Ravi", 50000)

object तयार करताना name आणि salary initialize होतात. एक technical clarification लक्षात ठेवा:

__init__() ला अनेक tutorials मध्ये constructor म्हटलं जातं, पण Python मध्ये object creation आणि initialization वेगवेगळ्या टप्प्यांमध्ये होतात. __new__() object तयार करण्यासाठी आणि __init__() तयार झालेल्या object ला initialize करण्यासाठी वापरली जाते.

बहुतेक सामान्य classes मध्ये तुम्हाला __new__() manually लिहिण्याची गरज पडत नाही.

हा topic real projects मध्ये खूप महत्त्वाचा आहे.

Instance Variable

प्रत्येक object साठी वेगळा data.

class Student:
    def __init__(self, name):
        self.name = name

इथे:

s1 = Student("Amit")
s2 = Student("Sneha")

name प्रत्येक object साठी वेगळं आहे.

Class Variable

Class level वर ठेवलेला attribute.

class Student:
    school_name = "ABC School"

    def __init__(self, name):
        self.name = name

आता:

s1 = Student("Amit")
s2 = Student("Sneha")

print(s1.school_name)
print(s2.school_name)

दोन्ही objects class attribute शोधू शकतात.

Python मध्ये class आणि instance attributes चं lookup behaviour समजून घेणं महत्त्वाचं आहे, कारण instance attribute आणि class attribute एकाच नावाने असतील तर instance-level value ला precedence मिळते.

OOP शिकताना खालील चार concepts सर्वाधिक चर्चेत येतात:

  1. Inheritance
  2. Polymorphism
  3. Encapsulation
  4. Abstraction

पण एक महत्त्वाची गोष्ट:

हे चार शब्द फक्त definitions म्हणून पाठ करण्यापेक्षा problem solve करताना त्यांचा उपयोग काय आहे हे समजणं जास्त महत्त्वाचं आहे.

Inheritance म्हणजे काय?

Inheritance मध्ये एक class दुसऱ्या class मधील behaviour किंवा attributes reuse करू शकतो.

उदा.:

class Animal:
    def eat(self):
        print("Animal खात आहे")


class Dog(Animal):
    def bark(self):
        print("Dog भुंकत आहे")

आता:

dog = Dog()

dog.eat()
dog.bark()

Dog class मध्ये eat() लिहिलेली नाही, तरी ती Animal कडून मिळते.

Inheritance चा फायदा

जर अनेक classes मध्ये common behaviour असेल तर ते पुन्हा पुन्हा लिहिण्याची गरज कमी होते.

उदा.:

Animal
 ├── Dog
 ├── Cat
 └── Cow

Common behaviour Animal मध्ये ठेवता येतो.

पण प्रत्येक वेळी inheritance वापरायचं का?

नाही. फक्त code reuse करण्यासाठी inheritance वापरणं योग्य design असेलच असं नाही.

जर relationship स्पष्टपणे “is-a” असेल तर inheritance विचारात घेता येतो.

उदा.:

Dog is an Animal
Car is a Vehicle

पण:

Car has an Engine

इथे inheritance पेक्षा Composition जास्त natural आहे.

Polymorphism म्हणजे एकाच interface किंवा method call ला वेगवेगळ्या objects कडून वेगवेगळं behaviour मिळणं.

उदा:

class Dog:
    def sound(self):
        print("भुंकणे")


class Cat:
    def sound(self):
        print("म्याव")


animals = [Dog(), Cat()]

for animal in animals:
    animal.sound()

Output:

भुंकणे
म्याव

Loop ला हे माहीत असण्याची गरज नाही की object Dog आहे की Cat.

त्याला फक्त एवढं माहीत आहे:

animal.sound()

यामुळे code अधिक flexible होतो. Python मध्ये यासोबत duck typing ही कल्पना देखील महत्त्वाची आहे. म्हणजे object कोणत्या class चा आहे यापेक्षा तो आवश्यक behaviour देतो का हे अनेक परिस्थितींमध्ये अधिक महत्त्वाचं ठरतं.

Encapsulation म्हणजे data आणि त्या data वर काम करणारा logic एका class मध्ये organize करून बाहेरून होणाऱ्या चुकीच्या manipulation वर नियंत्रण ठेवण्याची design पद्धत.

उदा. Bank Account:

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def get_balance(self):
        return self.__balance

आता:

account = BankAccount(1000)

account.deposit(500)

print(account.get_balance())

Output:

1500

इथे balance वर थेट काम करण्याऐवजी deposit() सारख्या method मधून rule लागू करता येतो.

उदा.:

if amount > 0:

यामुळे invalid amount थांबवता येतो.

इथे एक common misconception आहे. Python मध्ये Java किंवा C++ सारखं strict private access control नाही.

Double underscore:

self.__balance

यामुळे name mangling होतं.

म्हणून __balance हा attribute normal बाह्य access पासून लपवण्यास मदत करतो, पण तो security boundary नाही.

म्हणून:

Encapsulation म्हणजे “data पूर्णपणे inaccessible करणे” नाही; controlled access आणि implementation details व्यवस्थित organize करणे हा त्याचा practical उपयोग आहे.

Python च्या documentation मध्येही private variables बाबत Python ची approach convention आणि name mangling वर आधारित असल्याचं स्पष्ट केलं आहे.

Abstraction म्हणजे user ला आवश्यक interface देणे आणि implementation ची अनावश्यक complexity मागे ठेवणे.

उदा. ATM वापरताना तुम्ही:

  • पैसे काढता
  • balance check करता
  • PIN वापरता

पण transaction database मध्ये कशी process होते, authentication कसं होतं, backend मध्ये कोणते queries चालतात हे प्रत्येक user ला माहीत असण्याची गरज नसते.

Python मध्ये abstract base classes तयार करण्यासाठी abc module वापरता येतो.

from abc import ABC, abstractmethod


class Payment(ABC):

    @abstractmethod
    def pay(self, amount):
        pass


class UPI(Payment):

    def pay(self, amount):
        print(f"UPI द्वारे ₹{amount} payment झाले")


class Card(Payment):

    def pay(self, amount):
        print(f"Card द्वारे ₹{amount} payment झाले")

आता:

payments = [UPI(), Card()]

for payment in payments:
    payment.pay(1000)

इथे Payment एक common interface देतो आणि प्रत्येक implementation आपापल्या पद्धतीने pay() करते.

हे दोन concepts beginners अनेकदा एकसारखे समजतात.

सोपं लक्षात ठेवा:

Encapsulation

Data आणि behaviour कसं organize आणि control करायचं?

उदा.:

self.__balance

Abstraction

User ला काय interface द्यायचं आणि implementation मधील complexity किती लपवायची?

उदा.:

payment.pay(1000)

User ला payment process ची पूर्ण internal implementation माहित असण्याची गरज नाही.

थोडक्यात:

Encapsulation → How to control/organize?
Abstraction   → What should the user need to know?

Inheritance वापरताना child class मधून parent class ची functionality वापरण्यासाठी super() उपयोगी पडतो.

class Person:
    def __init__(self, name):
        self.name = name


class Student(Person):
    def __init__(self, name, marks):
        super().__init__(name)
        self.marks = marks

इथे:

super().__init__(name)

मुळे parent class चा initialization logic पुन्हा लिहावा लागत नाही. याचा फायदा म्हणजे common initialization logic एका ठिकाणी राहतो.

Child class parent class मधील method स्वतःच्या behaviour नुसार redefine करते, त्याला method overriding म्हणतात.

class Animal:
    def sound(self):
        print("Animal sound")


class Dog(Animal):
    def sound(self):
        print("Bark")

आता:

dog = Dog()
dog.sound()

Output:

Bark

Dog ने parent च्या sound() ला स्वतःच्या implementation ने override केलं.

Instance Method

Object च्या data वर काम:

class Student:

    def __init__(self, name):
        self.name = name

    def show_name(self):
        return self.name

इथे self वापरला आहे.

Class Method

Class level data किंवा alternate object creation सारख्या use cases साठी cls वापरला जातो.

class Student:

    school = "ABC School"

    @classmethod
    def change_school(cls, name):
        cls.school = name

Static Method

Object किंवा class च्या state ची गरज नसलेला related utility logic class मध्ये ठेवायचा असेल तर staticmethod वापरता येतो.

class Student:

    @staticmethod
    def is_pass(marks):
        return marks >= 35

यात self किंवा cls ची गरज नाही.

लक्षात ठेवण्याचा सोपा rule

self → Object-level data
cls  → Class-level data
none → Independent utility logic

हा topic beginner tutorials मध्ये अनेकदा दुर्लक्षित केला जातो, पण practical software design मध्ये तो महत्त्वाचा आहे.

समजा:

Car has an Engine

Engine हा Car चा प्रकार नाही.

म्हणून:

class Engine:
    def start(self):
        print("Engine started")


class Car:
    def __init__(self):
        self.engine = Engine()

    def start(self):
        self.engine.start()
        print("Car started")

इथे Car मध्ये Engine चा object आहे. याला Composition म्हणतात.

फरक

Inheritance:
Dog is an Animal

Composition:
Car has an Engine

Inheritance मध्ये “is-a” relationship असतो. Composition मध्ये “has-a” relationship असतो.

Real project मध्ये कोणता approach वापरायचा हे relationship, responsibilities आणि future changes यावर अवलंबून असतं. फक्त code reuse करण्यासाठी inheritance निवडण्यापेक्षा design relationship समजून घेणं महत्त्वाचं आहे.

आता वेगवेगळे concepts वेगवेगळे पाहण्यापेक्षा त्यांना एका छोट्या project मध्ये जोडूया. समजा आपण Employee Management System चा basic भाग बनवत आहोत.

आपल्याकडे:

Employee
   ↓
Developer
   ↓
Manager

पण Developer आणि Manager दोघांकडे common employee information आहे.

म्हणून base class:

class Employee:

    company = "Learn Grow"

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def show_details(self):
        print(f"Name: {self.name}")
        print(f"Salary: ₹{self.salary}")

    def work(self):
        print("Employee is working")

आता Developer:

class Developer(Employee):

    def __init__(self, name, salary, language):
        super().__init__(name, salary)
        self.language = language

    def work(self):
        print(f"{self.name} {self.language} मध्ये coding करत आहे")

Manager:

class Manager(Employee):

    def work(self):
        print(f"{self.name} team manage करत आहे")

आता objects:

employees = [
    Developer("Amit", 60000, "Python"),
    Manager("Sneha", 80000)
]

आणि:

for employee in employees:
    employee.show_details()
    employee.work()

इथे एकाच list मध्ये वेगवेगळ्या प्रकारचे objects आहेत.

पण:

employee.work()

केल्यावर object नुसार वेगळं behaviour मिळतं. यातून आपल्याला एकाच छोट्या project मध्ये:

  • Class
  • Object
  • Instance variable
  • Class variable
  • Inheritance
  • super()
  • Method overriding
  • Polymorphism

हे concepts दिसतात. याच प्रकारे मोठ्या application मध्ये classes एकमेकांशी काम करतात.

हा प्रश्न “OOP म्हणजे काय?” पेक्षा काही वेळा जास्त महत्त्वाचा आहे. प्रत्येक Python program साठी class बनवण्याची गरज नसते.

छोटा script

उदा.:

a = 10
b = 20

print(a + b)

इथे OOP वापरण्याची गरज नाही.

Simple utility

एखादं छोटं calculation किंवा file conversion script असेल तर functions पुरेसे असू शकतात.

मोठं application

उदा.:

  • E-commerce application
  • Banking system
  • Student Management System
  • Inventory Management
  • Game
  • API backend
  • मोठं automation framework

अशा systems मध्ये अनेक entities आणि behaviours असल्यामुळे OOP उपयोगी ठरू शकतं.

साधा विचार

स्वतःला प्रश्न विचारा:

“या problem मध्ये अनेक entities आहेत का? प्रत्येक entity चा स्वतःचा data आणि behaviour आहे का?”

जर उत्तर हो असेल तर class-based design विचारात घेता येतो.

Python च्या ecosystem मध्ये OOP फक्त textbook topic नाही.

Web frameworks, libraries आणि applications मध्ये classes मोठ्या प्रमाणावर वापरल्या जातात.

उदा.:

Web Development

Django सारख्या frameworks मध्ये models, forms, views इत्यादी अनेक ठिकाणी class-based design आढळतो.

Game Development

Player
Enemy
Weapon
Game
Level

अशा entities classes म्हणून model करता येतात.

Automation

EmailSender
FileProcessor
ReportGenerator
DatabaseManager

प्रत्येकाची responsibility वेगळी ठेवता येते.

API / Backend

User
Product
Order
Payment
Notification

अशा entities चं logic व्यवस्थित organize करता येतं.

म्हणून OOP चा उद्देश फक्त “class कशी लिहायची?” एवढाच नाही.

मोठ्या codebase मध्ये responsibility व्यवस्थित organize करणं हा त्याचा practical फायदा आहे.

1. प्रत्येक गोष्टीसाठी class तयार करणे

OOP शिकल्यानंतर काही beginners प्रत्येक छोट्या function साठी class तयार करतात.

हे आवश्यक नाही. Simple problem असेल तर simple solution ठेवा.

2. self विसरणे

def show_name():

याऐवजी instance method मध्ये:

def show_name(self):

3. Class variable आणि instance variable गोंधळणे

class Student:
    school = "ABC"

    def __init__(self, name):
        self.name = name

school आणि name ची भूमिका वेगळी आहे.

4. फक्त code reuse साठी inheritance वापरणे

Inheritance वापरण्यापूर्वी relationship विचारात घ्या.

is-a → Inheritance विचारात घ्या
has-a → Composition विचारात घ्या

हा कठोर नियम नाही, पण design करताना उपयोगी starting point आहे.

5. __private म्हणजे security असा गैरसमज

Python मधील name mangling हा security mechanism नाही. Sensitive data साठी actual security mechanisms वेगळे असतात.


Q1. Class आणि Object मध्ये नेमका फरक काय?

Ans: Class हा एक blueprint/साचा आहे, तर Object हा त्या साच्यावरून तयार झालेली प्रत्यक्ष वस्तू आहे. एका class पासून अनेक objects बनवता येतात.

Q2. self का लागतो, आणि तो का लिहायला विसरला जातो?

Ans: self म्हणजे “हा विशिष्ट object.” प्रत्येक instance method मध्ये पहिला parameter म्हणून तो लागतोच, कारण Python ला कळायला हवं की कोणत्या object वर काम करायचं आहे. सुरुवातीला विसरला जातो कारण तो implicitly (आपोआप) पास होतो, त्यामुळे तो “दिसत” नाही.

Q3. Encapsulation खरंच data पूर्णपणे लपवतं का?

Ans: नाही, पूर्णपणे नाही. Python मध्ये खरी “private” संकल्पना नाही — __balance सारखे attributes फक्त name-mangling मुळे थेट access करणं अवघड होतं, पण _ClassName__balance असं लिहून तांत्रिकदृष्ट्या access करता येतं. हे फक्त एक convention आणि best-practice आहे, कडक सुरक्षा नाही.

Q4. Multiple inheritance म्हणजे काय, आणि ती वापरावी का?

Ans: एक class एकापेक्षा जास्त parent classes कडून inherit करू शकतो. उदा. class C(A, B):. ही सुविधा आहे, पण जास्त वापरल्यास कोड गुंतागुंतीचा होतो (यालाच “Diamond Problem” म्हणतात) — त्यामुळे गरज असेल तेव्हाच वापरावी.

Blogger Rupesh

Blogger Rupesh

माझं नाव रुपेश आहे, आणि मी एक Blogger तसेच Content Writer आहे. मी माझा ब्लॉगिंगचा प्रवास वयाच्या ३० व्या वर्षी सुरू केला आणि आज मला या क्षेत्रात ५ वर्षांचा अनुभव आहे.माझा ब्लॉग “Learn Grow” मराठी भाषेत असून, त्यावर मी Blogging, Education, Programming शिकणे आणि AI Tools यांसारख्या महत्त्वाच्या विषयांवर सोप्या आणि समजण्यासारख्या भाषेत माहिती शेअर करतो. यासोबतच, मी Freelancing Services देखील प्रदान करतो, ज्यामध्ये Content Writing, SEO आणि Digital Marketing संबंधित कामांचा समावेश आहे.

Scroll to Top