Exercises — Functions — def, parameters, return, docstrings
1.2.27 · D4· Coding › Introduction to Programming (Python) › Functions — def, parameters, return, docstrings
Woh mental model jis par hum poore time lean karte hain:

Ek function ek box hai: arguments upar ke slots mein jaate hain (parameters), andar hidden kaam hota hai, aur exactly ek value neeche return ke zariye bahar girta hai. Neeche har exercise asal mein yeh poochh rahi hai: "kya andar jaata hai, kya bahar aata hai, aur andar kya hota hai."
L1 — Recognition
Goal: parts ko identify karo. Abhi apne dimag mein code mat chalao — bas cheezein naam karo.
Exercise 1.1
Neeche ke code mein, woh keyword jo definition shuru karta hai, parameter(s), aur docstring ko naam do.
def triple(x):
"""Return x multiplied by three."""
return x * 3Recall Solution 1.1
- Keyword jo definition shuru karta hai :::
def - Parameter :::
x(defline mein placeholder naam) - Docstring :::
"""Return x multiplied by three."""—defke bilkul neeche pehla string literal.
Humne kya kiya: box-picture mein har word ko uski job se match kiya. def box kholti hai, x upar ka slot hai, docstring side par laga sticker label hai.
Exercise 1.2
Call triple(4) ke liye, kya 4 ek parameter hai ya argument? Kya value bahar aati hai?
Recall Solution 1.2
4hai ek ::: argument — woh actual value joxnaam ke slot ko bharta hai.- Return ki gayi value :::
12, kyunki4 * 3 = 12.
Slot vs filling: x slot hai (parameter), 4 woh hai jo tum usme daalte ho (argument).
L2 — Application
Goal: scratch se functions likho jo actually sahi value return karein.
Exercise 2.1
Ek function rectangle_area(width, height) likho ek docstring ke saath jo area ko return kare (print nahi). Phir batao ki rectangle_area(3, 4) kya deta hai.
Recall Solution 2.1
def rectangle_area(width, height):
"""Return the area of a rectangle: width times height."""
return width * heightrectangle_area(3, 4) → ::: 12.
Kya / Kyun / Kaisa dikhta hai: humne return use kiya (print nahi) taaki caller aur zyada math kar sake answer ke saath, jaise total = rectangle_area(3, 4) + 5. Box picture mein, 12 neeche se bahar girta hai — woh sirf screen par nahi dikhta.
Exercise 2.2
to_celsius(f) likho jo Fahrenheit mein temperature ko Celsius mein convert kare, formula use karke. to_celsius(212) aur to_celsius(32) ka result do.
Recall Solution 2.2
def to_celsius(f):
"""Return the Celsius value for a Fahrenheit temperature f."""
return (f - 32) * 5 / 9to_celsius(212):::100.0— ubalte paani ka temperature.to_celsius(32):::0.0— jamte paani ka temperature.
/ 9 kyun aur // 9 kyun nahi? Hume exact fractional result chahiye, isliye hum ordinary division / use karte hain (jo float return karta hai). Integer division // fractional part throw kar deta aur un temperatures ke liye galat answers deta jo evenly divide nahi hote.
L3 — Analysis
Goal: apne dimag mein code chalao. Exactly predict karo kya hoga.
Exercise 3.1
Yeh program kya print karta hai?
def f():
print("a")
x = f()
print(x)Recall Solution 3.1
Yeh do lines print karta hai:
a
None
::: a f ke andar print("a") se aata hai. Phir f mein koi return nahi hai, isliye call f() evaluate hoti hai None mein; x = None; print(x) dikhata hai None.
Kyun: printing aur returning alag-alag channels hain. f display channel (print) use karta hai lekin return channel khaali chhodd deta hai → None.
Exercise 3.2
Output predict karo:
def g(n):
if n > 0:
return "positive"
print("still running")
return "not positive"
print(g(5))
print(g(-2))Recall Solution 3.2
positive
still running
not positive
::: g(5) ke liye: 5 > 0 true hai, isliye return "positive" fire hoti hai aur function turant exit kar jaata hai — print("still running") line kabhi nahi pahunchi jaati. g(-2) ke liye: -2 > 0 false hai, pehla return skip hota hai, print("still running") chalata hai, phir return "not positive".
Box mein kaisa dikhta hai: return ek trapdoor hai. Ek baar usme se gir gaye, us path par neeche ka koi code nahi chalta. -2 wala path box mein se alag route leta hai, raaste mein print ko hit karta hai.
Exercise 3.3
p, q = h(9) p aur q ko kya bind karta hai?
def h(a):
"""Return the number and its square."""
return a, a * aRecall Solution 3.3
p:::9q:::81
Kyun: return a, a * a dono values ko ek tuple (9, 81) mein pack karta hai. Line p, q = h(9) phir us tuple ko unpack karti hai — pehla slot p ko, doosra q ko. (Packing/unpacking ke liye Lists and Tuples dekho.)
L4 — Synthesis
Goal: parameters, defaults, keywords, aur control flow ko combine karo.
Exercise 4.1
power(base, exp=2) likho jo base ** exp return kare, default squaring ke liye. power(5), power(2, 3), aur power(exp=3, base=2) ke outputs do.
Recall Solution 4.1
def power(base, exp=2):
"""Return base raised to exp; squares by default."""
return base ** exppower(5):::25—expchhoda gaya, isliye default2use hoti hai: .power(2, 3):::8—3position seexpfill karta hai: .power(exp=3, base=2):::8— keyword arguments naam se match karte hain, isliye order matter nahi karta: .
Defaults kyun hote hain: woh ek definition ko "common case" (squaring) aur "general case" dono serve karne dete hain bina caller ko hamesha exp likhne par majboor kiye.
Exercise 4.2
clamp(x, low=0, high=10) likho jo x ko range [low, high] mein force karke return kare: agar x low se neeche ho toh low return karo, agar high se upar ho toh high return karo, warna x return karo. clamp(5), clamp(-3), clamp(99), aur clamp(5, low=6) do.
Recall Solution 4.2
def clamp(x, low=0, high=10):
"""Return x limited to the range [low, high]."""
if x < low:
return low
if x > high:
return high
return xclamp(5):::5— pehle se[0, 10]ke andar hai.clamp(-3):::0—lowse neeche,0tak snap up.clamp(99):::10—highse upar,10tak snap down.clamp(5, low=6):::6— ab5 < 6hai, isliye nayelowtak snap up.
Teen returns kyun aur elif nahi? Har early return decide hote hi exit karta hai — Control Flow — if statements dekho. Final return x sirf tab pahuncha jaata hai jab koi bhi bound violate nahi hua. Humne teeno cases cover kiye: neeche, upar, aur andar.
L5 — Mastery
Goal: subtle edge cases — mutable defaults, None sentinel, degenerate inputs.
Exercise 5.1 (classic trap)
Do printed lists predict karo:
def add_item(item, bag=[]):
bag.append(item)
return bag
print(add_item("apple"))
print(add_item("banana"))Recall Solution 5.1
['apple']
['banana', 'apple'] # NOT what most people expect
Ruko — dhyan se padho. Output hai:
['apple']
['apple', 'banana']
::: Default list [] ek baar banti hai, definition ke time par, aur har us call mein share hoti hai jo bag chhod deta hai. Pehli call "apple" append karti hai → ['apple']. Doosri call usi list ko reuse karti hai aur "banana" append karti hai → ['apple', 'banana'].
Sabko kyun surprise karta hai: [] lagta hai jaise iska matlab hai "har baar ek fresh khaali list," lekin yeh ek baar evaluate hoti hai jab def chalta hai, har call par ek baar nahi. Box wahi list hamesha ke liye yaad rakhta hai.
Exercise 5.2 (fix)
add_item ko rewrite karo taaki bina bag ke har call ek fresh khaali list se shuru ho. Do consecutive calls ke outputs do.
Recall Solution 5.2
def add_item(item, bag=None):
"""Append item to bag; start a new list if none is given."""
if bag is None:
bag = []
bag.append(item)
return bag
print(add_item("apple")) # ['apple']
print(add_item("banana")) # ['banana']- Pehli call :::
['apple'] - Doosri call :::
['banana']
None sentinel kyun kaam karta hai: None safe "kuch pass nahi hua" flag hai. Line bag = [] ab function body ke andar chalti hai, isliye har call par ek brand-new list banti hai jise uski zaroorat hai. Har call ko apni fresh list milti hai — koi shared memory nahi. (Dekho Variables and Scope: ab bag har baar ek fresh local hai.)
Exercise 5.3 (degenerate input)
def safe_divide(a, b): ke liye ek function likho jo quotient a / b return kare, lekin string "undefined" return kare jab b == 0 (division by zero) ho. safe_divide(10, 2), safe_divide(7, 0), aur safe_divide(0, 5) do.
Recall Solution 5.3
def safe_divide(a, b):
"""Return a / b, or 'undefined' when b is zero."""
if b == 0:
return "undefined"
return a / bsafe_divide(10, 2):::5.0safe_divide(7, 0):::"undefined"— hum zero case ko divide karne se pehle guard karte hain, isliye Python kabhiZeroDivisionErrorraise nahi karta.safe_divide(0, 5):::0.0— zero numerator bilkul theek hai; . Sirf zero denominator degenerate hai.
Saare cases covered: normal divisor, zero divisor (guarded), aur zero dividend (allowed). Order matter karta hai — pehle b == 0 check karo, kyunki b ke 0 hone par a / b ko touch karna kisi bhi baad ke check ke help karne se pehle crash kar deta hai.
Recall Feynman recap
Yeh das problems paanch heights se dekha gaya ek hi idea hai: ek function ek labelled box hai input slots aur ek output chute ke saath. L1 parts ko naam deta hai, L2 boxes banata hai, L3 trace karta hai kya bahar girata hai, L4 defaults aur branches ko box mein wire karta hai, L5 un boxes ko handle karta hai jo secretly yaad rakhti hain (mutable defaults) ya toot jaati hain (divide by zero). Pehle guard karo, ek baar return karo, aur kabhi ek number dikhane ko ek number dene se confuse mat karo.
Connections
- Parent topic — Functions
- Variables and Scope — kyun
None-sentinel fix har call ko ek fresh local list deta hai. - Control Flow — if statements —
clampaursafe_dividemein branchingreturns. - Lists and Tuples — Exercise 3.3 mein tuple packing/unpacking.
- Recursion — agla step: ek box jo khud ko call karta hai.
- Lambda and Higher-order Functions — one-line anonymous functions.
- DRY Principle — woh reason jiske liye yeh sab exist karta hai.