1.2.27 · D3 · Coding › Introduction to Programming (Python) › Functions — def, parameters, return, docstrings
Intuition Ek poore page ke examples kyun?
Tumne functions ke parts already parent note pe dekhe hain: def, parameters, return, docstrings. Parts jaanna ek toolbox rakhne jaisa hai. Yeh page hai workshop : hum har tarah ka kaam is machine se run karte hain, taaki jab exam (ya real code) koi ajeeb case throw kare, tumne woh pehle dekha hua ho .
Ek function ko sirf itne hi fundamentally alag tareekon se pakda ja sakta hai. Neeche har "cell" hai — har distinct behaviour class jo is topic mein chhupa hua hai. Baad ke examples mein se har ek us cell se tagged hai jo woh cover karta hai, taaki milke koi gap na rahe .
Cell
Kya isse alag banata hai
Example jo isse cover karta hai
A. Basic value return
ek input, ek clean returned value
Ex 1
B. No return
body run hoti hai, lekin kuch wapas nahi aata → None
Ex 2
C. print vs return confusion
screen pe same dikhta hai, behave alag karta hai
Ex 2
D. Multiple return values
tuple packing / unpacking
Ex 3
E. Default parameter used / overridden
argument omit kiya vs supply kiya
Ex 4
F. Keyword args reorder
names position ko beat karte hain
Ex 4
G. Degenerate / edge input
zero, empty, boundary values
Ex 5
H. Early return (branching exit)
return if ke andar, baad ka code skip
Ex 6
I. Mutable default trap
shared-list bug
Ex 7
J. Real-world word problem
ek story ko function mein translate karna
Ex 8
K. Exam-style twist
ek tricky call trace karo, exact output predict karo
Ex 9
Arguments ke teen "flavours" (positional / keyword / default) cells E aur F mein hain; branching logic Control Flow — if statements se lete hain; tuple return Lists and Tuples se lete hain; poori motivation DRY Principle hai.
Worked example Ek basic value return
def square (n):
"""Return n multiplied by itself."""
return n * n
y = square( 6 )
Forecast: aage padhne se pehle — y kya hai? Kya yeh kahin print hota hai?
Python square(6) se milta hai aur square naam ke function object ko dhundta hai. Yeh step kyun? Naam sirf ek machine pe label hai; machine ko mila hona chahiye pehle woh run ho sake.
Argument ko parameter se bind karo: n = 6. Kyun? Value 6 n naam ke slot mein slide ho jaati hai.
Body run karo: n * n = 6 * 6 = 36. Kyun? Yahi woh kaam hai jo machine karne ke liye bani thi.
return 36 — call expression square(6) ban jaata hai value 36, aur function exit ho jaata hai. Kyun? return ek saath do kaam karta hai: value wapas bhi deta hai aur ruk bhi jaata hai.
y = 36. Kuch print nahi hota — y sirf value hold karta hai. Kyun? Assignment jo bhi call evaluate kare usse capture kar leti hai.
Verify: 6 × 6 = 36 . Ek puri number ka square ek grid ke roop mein us number ka area hai — ek 6 × 6 grid mein 36 cells hote hain. ✓
Worked example Gum hota hua jawab
def show_square (n):
print (n * n) # displays, but does NOT return
z = show_square( 6 )
print (z)
Forecast: Do cheezein print hoti hain. Dono lines exactly guess karo.
show_square(6) run hota hai: print(36) screen pe 36 dalta hai. Yeh step kyun? print ek side effect hai — woh insaan se baat karta hai.
Function apne end pe pahunchta hai bina return ke. Toh call quietly None return kar deta hai. Kyun? Har function ko kuch na kuch wapas dena hota hai; jab tum nahi batate kya, Python "kuch nahi" wali value None wapas de deta hai.
z = None. Kyun? Call None evaluate hua, aur assignment woh copy kar leti hai.
print(z) screen pe None dalta hai. Kyun? Humne use kaha ki z jo bhi hold kare dikhao.
Verify: Output do lines hai — pehle 36 phir None. Ex 1 se compare karo: wahan y kaam aane wala 36 tha; yahan z aage ke maths ke liye useless hai. Yahi poora print-vs-return ka lesson ek experiment mein hai. ✓
Common mistake "Maine number dekha, toh number mila"
Galat feeling: screen pe 36 hi returned value hai. Yeh Ex 1 ke result se bilkul identical dikhta hai.
Fix: screen woh dikhata hai jo print display karta hai; caller woh receive karta hai jo return wapas deta hai . Yahan kuch wapas nahi diya gaya → None.
Worked example Quotient aur remainder saath mein
def divmod2 (a, b):
"""Return (quotient, remainder) of a divided by b."""
return a // b, a % b
q, r = divmod2( 17 , 5 )
Forecast: q aur r kya hain? Aur divmod2 actually kaunsa type return karta hai?
a = 17, b = 5 bind karo. Yeh step kyun? Dono slots position ke hisaab se bharo.
a // b = 17 // 5 = 3 — integer (floor) division, "17 mein poore 5 kitne fit hote hain". Kyun? // fractional part hata deta hai, whole groups deta hai.
a % b = 17 % 5 = 2 — remainder, "kya bacha rehta hai". Kyun? % un whole groups ke baad jo bachta hai woh hai.
return 3, 2 — comma ek tuple (3, 2) banata hai. Kyun? Ek function sirf ek object wapas de sakta hai, toh Python dono ko ek tuple mein bundle kar deta hai (dekho Lists and Tuples ).
q, r = (3, 2) — tuple unpacking isse split karta hai: q = 3, r = 2. Kyun? Left side mein do names hain, right side mein do slots — woh line up ho jaate hain.
Verify: original rebuild karo: q × b + r = 3 × 5 + 2 = 17 = a . ✓ Identity a = ( a // b ) ⋅ b + ( a % b ) hamesha hold karni chahiye.
Worked example Ek function, teen call styles
def power (base, exp = 2 ):
"""Return base raised to exp; squares by default."""
return base ** exp
a = power( 5 ) # (i)
b = power( 2 , 3 ) # (ii)
c = power( exp = 3 , base = 2 ) # (iii)
Forecast: a, b, c predict karo — aur note karo kaunsi call inputs reorder karti hai.
(i) power(5): sirf base supply hua, toh base = 5. exp omit kiya → apne default 2 pe fall back karta hai. Result 5 ** 2 = 25. Yeh step kyun? Ek default parameter apna slot bharta hai jab caller chup rahe.
(ii) power(2, 3): position se match kiya → base = 2, exp = 3. Result 2 ** 3 = 8. Kyun? Jab koi naam nahi diye, Python arguments ko left-to-right line up karta hai.
(iii) power(exp=3, base=2): naam se match kiya, toh line pe order irrelevant hai → base = 2, exp = 3. Result 2 ** 3 = 8. Kyun? Keyword arguments explicitly batate hain kaunsa slot , position ko override karte hue.
Verify: 5 2 = 25 , 2 3 = 8 , 2 3 = 8 . Calls (ii) aur (iii) same filling alag order mein naam karte hain aur sahi same 8 dete hain. ✓
Worked example Edges pe kya hota hai?
def average (numbers):
"""Return the mean of a list of numbers."""
return sum (numbers) / len (numbers)
average([ 4 , 6 , 8 ]) # (i) normal
average([ 7 ]) # (ii) single element
average([]) # (iii) empty <-- danger
Forecast: Inmen se kaunsa toot jaata hai, aur kyun?
(i) sum([4,6,8]) = 18, len = 3, toh 18 / 3 = 6.0. Yeh step kyun? Mean hai total divided by count.
(ii) sum([7]) = 7, len = 1, toh 7 / 1 = 7.0. Kyun? Ek item ka average woh item khud hota hai — ek healthy boundary case.
(iii) sum([]) = 0, len = 0, toh 0 / 0 → ZeroDivisionError , ek crash. Kyun? Zero se divide karne ka koi jawab nahi; empty list ke paas divide karne ke liye koi count nahi.
Ek robust version degenerate case ko guard karta hai (Control Flow — if statements se lete hue):
def average (numbers):
"""Return the mean, or None for an empty list."""
if len (numbers) == 0 :
return None # early exit for the degenerate input
return sum (numbers) / len (numbers)
Verify: normal = 6.0, single = 7.0, empty ab crash hone ki jagah None return karta hai. ✓ Ab har input class handle ho gayi.
return ke baad ka code kabhi nahi chalta
def classify (n):
"""Return 'zero', 'negative', or 'positive'."""
if n == 0 :
return "zero"
if n < 0 :
return "negative"
return "positive"
classify( 0 ) # (i)
classify( - 4 ) # (ii)
classify( 9 ) # (iii)
Forecast: classify(0) ke liye, kya baad wala if n < 0 aur final return kabhi execute hote hain?
(i) n = 0: pehla if true hai → return "zero". Function turant exit ho jaata hai; n < 0 check aur last return kabhi reach nahi hote. Yeh step kyun? return machine ko ussi jagah rok deta hai — koi fall-through nahi.
(ii) n = -4: n == 0 false, skip. n < 0 true → return "negative". Kyun? Hum doosre test tak sirf isliye pahunche kyunki pehla fire nahi hua.
(iii) n = 9: dono ifs false, toh final return "positive" pe fall karo. Kyun? Yeh catch-all hai jab upar kuch return nahi kiya.
Verify: outputs "zero", "negative", "positive" — n ka har sign (zero, negative, positive) ka exactly ek path hai, aur koi path apne return ke baad code nahi run karta. ✓
Worked example Woh list jo yaad rakhti hai
def add_item (x, bag = []): # DANGER: shared default list
bag.append(x)
return bag
print (add_item( 1 )) # (i)
print (add_item( 2 )) # (ii)
Forecast: Tum expect karte ho [1] phir [2]. Kya yahi hota hai?
Default [] ek baar create hota hai, us moment jab def run hota hai — har call pe nahi. Yeh step kyun? Default value function object ke saath store hoti hai, toh jo calls bag omit karti hain woh sab same list share karti hain.
(i) add_item(1): bag woh shared list hai, 1 append karo → [1], return aur print. Kyun? Shared list ka pehla mutation.
(ii) add_item(2): bag abhi bhi same list hai (ab [1] hai), 2 append karo → [1, 2]. Kyun? Woh kabhi reset nahi hua — default re-create nahi hua.
Verify: output hai [1] phir [1, 2], not [1] phir [2]. Bug real hai. Parent note ka None-sentinel fix har call mein fresh list deta hai:
def add_item (x, bag = None ):
if bag is None :
bag = [] # fresh list every call
bag.append(x)
return bag
Ab do calls [1] phir [2] dete hain — independent. ✓
Worked example Restaurant bill split karna
Ek group ne total rupees ka khana khaya. Woh tip percentage add karna chahte hain aur raqam ko people mein evenly split karna chahte hain. Ek function likho jo har insaan ki amount return kare, aur ise ₹800 bill, 10% tip, 4 log pe test karo.
Forecast: Roughly, kya har insaan ko ₹200 se thoda zyada ya kam dena chahiye? (200 no-tip split hai.)
Story ko inputs aur ek output mein translate karo. Yeh step kyun? Function ka kaam exactly "inputs → ek jawab" hai, toh pehle unhe naam dena machine clear kar deta hai.
def share_per_person (total, people, tip_percent = 10 ):
"""Return each person's share of total after adding tip_percent."""
grand_total = total * ( 1 + tip_percent / 100 )
return grand_total / people
Tip add karo: 800 * (1 + 10/100) = 800 * 1.1 = 880. Kyun? 10% tip bill ko 1.1 se multiply karta hai.
Logo mein split karo: 880 / 4 = 220. Kyun? Even split = grand total divided by head count.
tip_percent ka ek sensible default 10 hai, toh share_per_person(800, 4) bhi kaam karta hai. Kyun? Zyaatar groups ~10% tip karte hain; default typing bachata hai (cell E phir se).
Verify: har insaan ₹220 deta hai, jo ₹200 no-tip split se zyada hai exactly tip share se 4 800 × 0.10 = 4 80 = 20 . Units: rupees per person. ✓
Worked example Precise output predict karo
def f (a, b = 1 ):
"""Twist: a default AND an early return."""
if a > b:
return a - b
return b - a
print (f( 5 )) # (i)
print (f( 2 , 5 )) # (ii)
print (f( 3 , 3 )) # (iii)
Forecast: Check karne se pehle teeno printed numbers likh lo. Default aur equal case dekho.
(i) f(5): b omit kiya → default b = 1. Kya a > b? 5 > 1 true → return 5 - 1 = 4. Yeh step kyun? Default b fill karta hai, phir branch subtraction order choose karta hai.
(ii) f(2, 5): a = 2, b = 5. 2 > 5 false → skip, return 5 - 2 = 3 pe fall karo. Kyun? Jab a chhota hai, pehla return fire nahi karta, toh hum doosre tak pahunchte hain (cell H se early-return logic).
(iii) f(3, 3): a = 3, b = 3. 3 > 3 false (equal greater nahi hota) → return 3 - 3 = 0. Kyun? > boundary equality ko exclude karti hai, toh equal case doosre path se jaata hai.
Verify: outputs 4, 3, 0. Notice karo yeh function actually ∣ a − b ∣ compute karta hai, absolute difference — check: ∣5 − 1∣ = 4 , ∣2 − 5∣ = 3 , ∣3 − 3∣ = 0 . ✓ Har ordering (greater, smaller, equal) cover hai.
Recall Jawab chhupao — kya har cell yaad raha?
Basic return square(6)? ::: 36
z = show_square(6) phir print(z) kya print karta hai? ::: 36 phir None
divmod2(17, 5) q, r = deta hai? ::: q = 3, r = 2
power(exp=3, base=2)? ::: 8
Unguarded version mein average([]) kya karta hai? ::: ZeroDivisionError raise karta hai
Buggy shared default ke saath add_item(1) phir add_item(2) kya print karta hai? ::: [1] phir [1, 2]
share_per_person(800, 4) (10% default tip)? ::: 220.0
f(3, 3) jahan f a-b return karta hai agar a>b warna b-a? ::: 0
Mnemonic Matrix ek sar mein
"Value, Void, Vary, Verge, Vanish" → returns a V alue, ya V oid (None), V ary the args (defaults/keywords), V erge cases (zero/empty), aur V anishing early-returns.
Parent topic — the anatomy — yeh page uska "every scenario" workshop hai.
Control Flow — if statements — Ex 5, 6, 9 mein branching returns ko power karta hai.
Lists and Tuples — Ex 3 ke multiple return ke peeche tuple packing/unpacking.
Variables and Scope — Ex 7 mein mutable-default list ek single call se zyada kyun jeeti hai.
Lambda and Higher-order Functions — same input→output idea, ek line mein likha.
Recursion — ek function khud ko call karta hai, yahan trace kiye gaye usi return pe build.
DRY Principle — reason kyun upar ke har example ko function mein wrap karna worth tha.