1.3.6 · Coding › Python Intermediate
Intuition Ek-line mein poori picture
Ek function hamesha ek sensible value return nahi kar sakta. Agar aap int("hello") poochho, toh koi number dene ke liye hai hi nahi — toh fake answer se jhooth bolne ki jagah, Python ek exception raises karta hai: normal flow rok deta hai aur call stack mein upar tak "kuch galat hai!" chillata hai jab tak koi use catch na kare. raise woh tarika hai jisse TUMHARA code khud chillata hai jab use koi problem detect hoti hai.
answers ke liye hote hain. Exceptions "main jawab nahi de sakta" ke liye hote hain.
Socho ek withdraw(amount) method. Agar amount negative hai, toh -1 ya False return karna dangerous hai — caller use ignore karke corrupt data ke saath aage badh sakta hai. Raise karna caller ko majboor karta hai ki woh deal kare : ya toh handle karo ya loudly crash karo. Galat silent answers loud failures se bure hote hain.
Core trade-off (yahi 80/20 idea hai):
Return a value jab ek meaningful result ho (kabhi kabhi "not found" bhi).
Raise an exception jab continue karna ek bug ya invalid state hogi.
raise
Ek statement jo normal execution interrupt karta hai aur ek exception object ko call stack mein upar propagate karta hai. Syntax: raise SomeException("message"). raise ke baad jo cheez aati hai woh ek exception instance ya ek exception class honi chahiye (jise Python tumhare liye instantiate kar deta hai).
Definition Exception object
Ek class ka instance jo ultimately ==BaseException se inherit karta hai. Jo tum banate ho woh Exception== se inherit karte hain (BaseException se directly kabhi nahi). Jo message tum pass karte ho woh .args mein store hota hai.
raise ValueError ( "amount must be positive" ) # instance created from class + message
raise ValueError # class — Python instantiates it with no args
Jab raise run hota hai, Python yeh steps follow karta hai:
Exception object banao (agar tumne class di hai, toh use call karo).
Ek traceback attach karo jo record kare ki hum abhi kahan hain.
Current line chodo; bahar koi matching except dhoondo.
Is function ke andar enclosing try blocks check karo. Koi nahi? Yeh frame pop karo.
Caller ke frame mein repeat karo... upar aur upar.
Agar koi catch nahi karta, toh top tak pahunch jaata hai → program traceback print karta hai aur exit ho jaata hai.
Worked example Propagation trace karo
def a (): raise ValueError ( "boom" ) # (1) raised here
def b (): a() # (2) no try here → passes up
def c ():
try :
b() # (3) caught here!
except ValueError as e:
print ( "handled:" , e)
c() # prints: handled: boom
Yeh step kyun? Exception a ka baaki hissa, b ka baaki hissa skip kar deta hai, aur pehle matching except par land karta hai jo use upar chalte hue milta hai — c mein.
Intuition Built-ins generic hote hain; tumhari errors ka
matlab hota hai.
raise ValueError theek hai, lekin raise InsufficientFundsError callers ko except InsufficientFundsError: likhne deta hai aur us exact situation ko alag se handle karne deta hai — maan lo kisi typo se alag. Ek custom class ek named, catchable category hai.
Definition Custom exception
Ek class jo ==Exception== se (ya kisi aur specific built-in se) inherit karti hai. Aksar body sirf pass hoti hai — naam hi value hai.
class InsufficientFundsError ( Exception ):
"""Raised when a withdrawal exceeds the balance."""
pass
Kabhi kabhi handler ko sirf naam nahi, facts chahiye hote hain. __init__ add karo:
Worked example Custom exception jo attributes carry karta hai
class InsufficientFundsError ( Exception ):
def __init__ (self, balance, requested):
self .balance = balance
self .requested = requested
self .shortfall = requested - balance # why: precompute useful info
super (). __init__ ( # why: set the .args/message
f "Tried { requested } , only { balance } available."
)
try :
raise InsufficientFundsError( balance = 50 , requested = 80 )
except InsufficientFundsError as e:
print (e) # uses the message from super().__init__
print (e.shortfall) # 30 ← caller reads structured data
super().__init__(...) kyun? Yeh tumhara message e.args mein store karta hai taaki str(e) achhe se print ho aur base class sahi behave kare. Bhool gaye toh print(e) kuch nahi dikhayega.
raise
Kisi except block ke andar, akela raise us exception ko re-raise karta hai jo abhi handle ho rahi hai , uska original traceback preserve karta hai. "Dekho, log karo, phir jaane do" ke liye use hota hai.
raise B from A
B.__cause__ = A set karta hai, taaki traceback "The above exception was the direct cause..." dikhaye. Ise use karo kisi low-level error ko domain-level mein translate karne ke liye bina original chhupaye.
BaseException se inherit karna
Sahi lagta hai: "Yeh base hai, toh sabse generic hai — surely sahi parent hai."
Galat kyun hai: BaseException mein KeyboardInterrupt aur SystemExit bhi aate hain. Ek blanket except Exception: tumhari error ko (sahi tarike se) catch nahi karega agar yeh Exception ko bypass kar deti hai, aur tum accidentally Ctrl-C signals swallow kar sakte ho.
Fix: Hamesha ==Exception== se inherit karo.
Common mistake Exception ko
raise karna vs return karna
Sahi lagta hai: return ValueError("bad") — tumne object banaya, kaam ho gaya.
Galat kyun hai: Tumne exception banaya lekin kabhi throw nahi kiya; caller ko sirf ek normal object milta hai aur woh aage badh jaata hai.
Fix: raise ValueError("bad") use karo. Banana ≠ raise karna .
Common mistake Custom class mein
super().__init__() bhool jaana
Sahi lagta hai: "Maine apne attributes set kar diye, bas itna hi chahiye."
Galat kyun hai: str(e) / printed message empty hoga kyunki .args kabhi populate nahi hua.
Fix: super().__init__(message) call karo.
Common mistake "Safe rehne ke liye" bahut broadly catch karna
Sahi lagta hai: except Exception: pass crash nahi kar sakta, hai na?
Galat kyun hai: Yeh real bugs chhupa deta hai — tum silently woh errors swallow kar lete ho jo tumhara intention nahi tha.
Fix: Sabse narrow type catch karo; jo handle nahi kar sakte use re-raise karo.
Recall
raise ValueError aur raise ValueError("x") mein kya fark hai?
Pehla class pass karta hai; Python use bina message ke instantiate karta hai. Doosra ek instance pass karta hai jisme message .args mein stored hota hai. Dono kaam karte hain.
Recall Custom exceptions ko kis class se inherit karna chahiye, aur
BaseException se kyun nahi?
Exception se inherit karo. BaseException mein SystemExit/KeyboardInterrupt bhi aata hai, jo ordinary error handling mein nahi aana chahiye.
Recall
except ke andar bare raise kya karta hai?
Current exception ko uske original traceback ke saath re-raise karta hai.
Recall
raise B from A kya accomplish karta hai?
B.__cause__ = A set karta hai, exceptions ko chain karta hai taaki traceback original ko direct cause ke roop mein dikhaaye.
Recall Feynman: ek 12-saal ke bachchhe ko explain karo
Socho tum ek waiter ho order le rahe ho. Normally tum khaana laate ho (ek return value ). Lekin agar kitchen mein aag lagi ho, toh tum khaana nahi la sakte — balki tum "AAG LAGI HAI!" chillate hue bhaagoge (yahi raise hai). Jo bhi sune (except) decide kar sakta hai kya karna hai: 911 call karo, ya aur zor se chillao taaki upar manager sun sake (re-raise). Ek custom exception alag specific shouts rakhne jaisi hai: "AAG!", "PIZZA KHATAM!", "BAND HO GAYE!" — taaki sunne waale ko pata ho exactly kaun si problem handle karni hai.
R.A.I.S.E.
R eturn for answers, A bort with raise; I nherit from Exception; S uper().init for the message; E xcept the narrowest type.
Try-Except-Finally — raised exceptions kaise catch hote hain
Exception Hierarchy & BaseException — jisse tum inherit kar rahe ho
Classes and __init__ — custom exception ka constructor banana
Logging in Python — log-and-re-raise pattern
assert statement — ek halka cousin jo AssertionError raise karta hai
Python mein exception throw karne wala statement kaun sa hai? raise (followed by an exception instance or class)
Custom exceptions ko kis base class se inherit karna chahiye? Exception
BaseException se inherit kyun nahi karte?Isme SystemExit/KeyboardInterrupt bhi hai, jo normal handlers se catch nahi hone chahiye
except ke andar bare raise (no args) kya karta hai?Current exception ko re-raise karta hai, uska traceback preserve karte hue
raise B from A kya karta hai?Exceptions chain karta hai: B.__cause__ = A set karta hai taaki cause dikhe
Exception ka message kahan store hota hai? Uske .args tuple mein, super().__init__(msg) se set hota hai
raise ValueError aur raise ValueError("x") mein fark?Pehla class hai (auto-instantiated, no msg); doosra instance hai message ke saath
Error code return karne ki jagah raise kyun karo? Caller ko problem handle karne par majboor karta hai; silent corrupt-state continuation rokta hai
Agar koi except raised exception ko kabhi catch na kare toh kya hota hai? Yeh top tak propagate hota hai, traceback print hoti hai, aur program exit ho jaata hai
Data-carrying custom exception ko kaun sa method call karna chahiye, aur kyun? super().__init__(message) — .args populate karne ke liye taaki str(e) sahi print ho