Encapsulation — hiding internal state, name mangling (`__name`)
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__idChild.__id→_Child__id
Ab woh collide nahi karte — har class ke methods quietly apne version ko refer karte hain.

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.__balancea = Account(100)
print(a.get_balance()) # 100
a.__balance # AttributeError!
print(a._Account__balance) # 100 <- the mangled nameself.__balance__init__mein kyun? Yeh step kyun:__balancelikhne se mangling trigger hoti hai, toh yeh actually_Account__balancestore karta hai. Bahar sea.__balancetype karne wale ek non-existent attribute dhundhte hain →AttributeError. Invariant (balance >= 0) sirfdepositke through hi change ho sakta hai.a._Account__balancekyun 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__datac = Child()
print(c.reveal()) # "base secret" <- Base's data intact!
print(c.reveal_child()) # "child stuff"
print(c.__dict__) # {'_Base__data': ..., '_Child__data': ...}Child.__dataneBase.__datako clobber kyun nahi kiya? Yeh step kyun: har__datako 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 = -300ab setter chalata hai aur reject ho jaata hai, invariant protect karta hai — jabki callers phir bhi cleant.celsiussyntax use karte hain (koi uglyget_/set_nahi). fahrenheitread-only kyun hai? Yeh step kyun: koi setter define nahi, toh assign karne parAttributeErroraata 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?
Kya Python mein real private keyword hai?
_name, __name) plus name mangling use karta hai, hard enforcement nahi.Single leading underscore _name ka matlab kya hai?
Name mangling __x ko class Foo ke andar kya banata hai?
_Foo__x.Name mangling ka PURPOSE kya hai?
Kya tum bahar se mangled attribute access kar sakte ho?
obj._Foo__x.Kya __str__ name-mangled hai?
Kisi identifier ko mangle hone ke liye conditions kya hain?
Invariants protect karte hue controlled access expose karne ka Pythonic tarika kya hai?
@property getters/setters use karo.Read-only computed attribute kaise banate hain?
@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)