2.1.6 · HinglishOOP Fundamentals

Encapsulation — hiding internal state, name mangling (`__name`)

1,810 words8 min readRead in English

2.1.6 · Coding › OOP Fundamentals


Encapsulation HAI kya?


Python "private" signal kaise karta hai

Python mein Java jaisa koi hard private keyword nahi hai. Iske bajaye yeh conventions use karta hai, plus ek mild enforcement mechanism (name mangling).

Style Meaning Enforced?
name public
_name (one underscore) "internal, please don't touch" No — sirf convention
__name (two underscores) name-mangled, clashes avoid karta hai Yes (mild)
__name__ (dunder) special/magic, mangled NAHI

Name Mangling — woh ek asli mechanism

YE exist kyun karta hai? (Motivation scratch se derive karo)

Iska purpose security nahi hai. Yeh inheritance mein accidental name clashes avoid karne ke liye hai.

Socho ek Base class hai jisme ek internal __id hai, aur ek Child bhi __id naam ka attribute invent karta hai lekin bilkul alag purpose ke liye. Mangling ke bina, Child.__id silently Base.__id ko overwrite kar deta aur Base ke methods tod deta.

Mangling yeh kaise solve karta hai: interpreter har ek ko apni class ka naam deke rename kar deta hai:

  • Base.__id_Base__id
  • Child.__id_Child__id

Ab woh collide nahi karte — har class ke methods quietly apne version ko refer karte hain.

Figure — Encapsulation — hiding internal state, name mangling (`__name`)

Worked Example 1 — Ek self-guarding bank account

class Account:
    def __init__(self, balance):
        self.__balance = 0          # private internal state
        self.deposit(balance)       # go through the guard
 
    def deposit(self, amount):
        if amount < 0:                       # invariant check
            raise ValueError("no negatives")
        self.__balance += amount
 
    def get_balance(self):
        return self.__balance
a = Account(100)
print(a.get_balance())   # 100
a.__balance              # AttributeError!
print(a._Account__balance)  # 100  <- the mangled name
  • self.__balance __init__ mein kyun? Yeh step kyun: __balance likhne se mangling trigger hoti hai, toh yeh actually _Account__balance store karta hai. Bahar se a.__balance type karne wale ek non-existent attribute dhundhte hain → AttributeError. Invariant (balance >= 0) sirf deposit ke through hi change ho sakta hai.
  • a._Account__balance kyun kaam karta hai? Yeh step kyun: mangling sirf class body ke andar ke code ko rewrite karti hai. Bahar se tum mangled naam literally type kar sakte ho — yeh sabit karta hai ki yeh security nahi hai, bas clash-avoidance hai.

Worked Example 2 — Mangling inheritance collision rokta hai

class Base:
    def __init__(self):
        self.__data = "base secret"     # -> _Base__data
    def reveal(self):
        return self.__data              # compiled as self._Base__data
 
class Child(Base):
    def __init__(self):
        super().__init__()
        self.__data = "child stuff"     # -> _Child__data (different!)
    def reveal_child(self):
        return self.__data              # self._Child__data
c = Child()
print(c.reveal())        # "base secret"  <- Base's data intact!
print(c.reveal_child())  # "child stuff"
print(c.__dict__)        # {'_Base__data': ..., '_Child__data': ...}
  • Child.__data ne Base.__data ko clobber kyun nahi kiya? Yeh step kyun: har __data ko compile time par mangle kiya gaya tha uss class ka use karke jisme yeh likha gaya tha, jisse do alag keys ban gayi. Mangling ka poora point yahi hai.

Worked Example 3 — Properties: Pythonic tarika hide karne ka

Name mangling internal names ko protect karta hai, lekin controlled access expose karne ka idiomatic tarika hai @property.

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius           # single underscore: "internal"
 
    @property
    def celsius(self):                    # getter
        return self._celsius
 
    @celsius.setter
    def celsius(self, value):
        if value < -273.15:               # invariant: above absolute zero
            raise ValueError("below absolute zero")
        self._celsius = value
 
    @property
    def fahrenheit(self):                 # computed, read-only
        return self._celsius * 9/5 + 32
  • Property kyun, public attribute kyun nahi? Yeh step kyun: t.celsius = -300 ab setter chalata hai aur reject ho jaata hai, invariant protect karta hai — jabki callers phir bhi clean t.celsius syntax use karte hain (koi ugly get_/set_ nahi).
  • fahrenheit read-only kyun hai? Yeh step kyun: koi setter define nahi, toh assign karne par AttributeError aata hai; yeh derived state hai aur independently store nahi hona chahiye.

Common Mistakes (Steel-manned)


Recall Feynman: ek 12-saal ke bachchhe ko explain karo

Ek toy robot ke andar battery sealed hai. Tum usse remote se control karte ho — buttons for forward, turn, beep. Tum game ke beech battery nahi nikaal sakte, toh robot kabhi kisi weird tarike se achanak band nahi hoga. Woh sealed battery "private state" hai, aur remote "public interface" hai. Python mein __battery jaisa double underscore likhna aise hai jaise battery par apna secret nickname likhna taaki agar iss robot ke around koi bada robot bana diya gaya aur usme bhi battery ho, toh dono batteries mix nahi ho jayein. Yeh ek name tag hai, real lock nahi.


Flashcards

Encapsulation kya hai?
Data + methods ko ek unit mein bundle karna AUR internal state tak direct external access restrict karna, sirf ek controlled interface expose karna.
Kya Python mein real private keyword hai?
Nahi — yeh conventions (_name, __name) plus name mangling use karta hai, hard enforcement nahi.
Single leading underscore _name ka matlab kya hai?
Ek convention jो signal karta hai "internal, mat chhuona"; interpreter enforce nahi karta.
Name mangling __x ko class Foo ke andar kya banata hai?
_Foo__x.
Name mangling ka PURPOSE kya hai?
Class aur uske subclasses ke beech accidental name clashes rokna, security provide karna NAHI.
Kya tum bahar se mangled attribute access kar sakte ho?
Haan, uska mangled naam use karke, jaise obj._Foo__x.
Kya __str__ name-mangled hai?
Nahi — dunders (≥2 trailing underscores) mangling se exclude hain.
Kisi identifier ko mangle hone ke liye conditions kya hain?
Kam se kam 2 leading underscores AUR zyada se zyada 1 trailing underscore, class body ke andar likha gaya ho.
Invariants protect karte hue controlled access expose karne ka Pythonic tarika kya hai?
Validation ke saath @property getters/setters use karo.
Read-only computed attribute kaise banate hain?
Ek @property getter define karo bina setter ke.

Connections

  • OOP Fundamentals
  • Abstraction — hiding complexity behind interfaces
  • Inheritance — base and derived classes
  • Properties and Descriptors
  • Class Invariants & Validation
  • Access Modifiers (Java vs Python)

Concept Map

is

is

enables

enables

signaled by

convention only

mild enforcement

triggers

produces

purpose is to

not for

Encapsulation

Bundling data plus methods

Information hiding

Guard invariants

Free to change internals

Python conventions

_name single underscore

__name double underscore

Name mangling

Rewritten to _ClassName__name

Avoid inheritance name clashes

Not security