1.2.32 · D4 · HinglishIntroduction to Programming (Python)

ExercisesLambda functions — anonymous, used with map - filter

3,025 words14 min read↑ Read in English

1.2.32 · D4 · Coding › Introduction to Programming (Python) › Lambda functions — anonymous, used with map - filter

Shuru karne se pehle, ek mental picture jo tum is page par baar baar use karoge: apne data ko items ki ek conveyor belt samjho, aur lambda ko ek sticky-note rule jo tum ek worker ko dete ho. map ek aisa worker hai jo har item ko reshape karta hai; filter ek bouncer hai jo har item ko rakhta ya phenk deta hai. Neeche diya figure dekho aur ise dhyan mein rakho.

Figure — Lambda functions — anonymous, used with map - filter

Level 1 — Recognition

Exercise 1.1

Expression lambda x: x + 1 ki value kya hai? Choose: (a) number 1, (b) ek function object, (c) ek syntax error, (d) None.

Recall Solution

(b) ek function object. Ek lambda ek expression hai jo ek function tak evaluate hota hai. Ise akele likhne se yeh call nahi hota — yeh sirf helper ko create karta hai. Compare karo: 5 likhne se number 5 milta hai; lambda x: x+1 likhne se ek callable milta hai. Tum ise store kar sakte ho: f = lambda x: x + 1, phir f(4) se 5 milega. Yahi first-class idea hai — functions values hain jo tum idhar-udhar de sakte ho.

Exercise 1.2

Inme se kaunsa SyntaxError hai? A = lambda x: return x B = lambda x: x C = lambda: 42

Recall Solution

A ek SyntaxError hai. Lambda body ek single expression honi chahiye, aur uski value automatically return value hoti hai. return ek statement hai, expression nahi, isliye yahan forbidden hai. B theek hai (identity). C theek hai — lambda zero arguments le sakta hai; (lambda: 42)() 42 return karta hai.

Exercise 1.3

True ya false: map(f, it) ek list return karta hai.

Recall Solution

False. Python 3 mein, map ek lazy iterator return karta hai — yeh values on demand compute karta hai, ek ek karke, aur ek complete pass ke baad exhaust ho jaata hai. Saare results ek saath dekhne ke liye, ise wrap karo: list(map(f, it)). Yeh laziness Iterators and lazy evaluation ka topic hai.


Level 2 — Application

Exercise 2.1

Evaluate karo: list(map(lambda x: x * 3, [0, 1, 4]))

Recall Solution

map rule x * 3 ko har element par order mein apply karta hai:

  • 0 * 3 = 0
  • 1 * 3 = 3
  • 4 * 3 = 12

Result: [0, 3, 12].

Exercise 2.2

Evaluate karo: list(filter(lambda x: x > 5, [3, 8, 5, 10, 1]))

Recall Solution

filter har x ko tabhi rakhta hai jab predicate truthy ho (True), baaki ko drop karta hai. Har ek test karo:

  • 3 > 5 → False → drop
  • 8 > 5 → True → keep
  • 5 > 5 → False → drop (5 strictly 5 se bada nahi hai)
  • 10 > 5 → True → keep
  • 1 > 5 → False → drop

Result: [8, 10].

Exercise 2.3

Evaluate karo: sorted(['pear', 'fig', 'apple'], key=lambda s: len(s))

Recall Solution

sorted ko har item ke liye ek comparable value chahiye. Yahan key=lambda s: len(s) kehta hai "string length se compare karo":

  • 'pear' → 4
  • 'fig' → 3
  • 'apple' → 5

Un keys se ascending sort karne par (3, 4, 5): ['fig', 'pear', 'apple']. key ko har comparison par nahi, balki har item par ek baar kyun call kiya jaata hai? sorted ek strategy use karta hai jise decorate–sort–undecorate kehte hain. Pehle yeh decorate karta hai: tumhara key function har element par ek baar run karke result ko element ke saath pair karta hai, ek internal list banata hai jaise [(4,'pear'), (3,'fig'), (5,'apple')]. Phir woh un pairs ko computed key se sort karta hai. Aakhir mein undecorate karta hai: keys phenk deta hai aur elements ko nayi order mein return karta hai. Kyunki keys pehle compute aur store ho jaati hain, kisi item ki key sort ke dauran hone wali kai pairwise comparisons mein kabhi recompute nahi hoti — toh ek expensive key (maan lo ek database lookup) n baar chalti hai, n·log n baar nahi. Dekho sorted and key functions.

Exercise 2.4

Evaluate karo: list(map(lambda a, b: a + b, [1, 2, 3], [10, 20, 30]))

Recall Solution

map multiple iterables le sakta hai; yeh har ek se ek item kheenchta hai aur unhe two-argument lambda ko ek saath pass karta hai:

  • 1 + 10 = 11
  • 2 + 20 = 22
  • 3 + 30 = 33

Result: [11, 22, 33]. (Agar iterables ki length alag ho, toh map sabse chote par ruk jaata hai.)


Level 3 — Analysis

Exercise 3.1

Yeh code doosri line par empty list print karta hai. Kyun?

result = map(lambda x: x * x, [1, 2, 3])
print(list(result))   # [1, 4, 9]
print(list(result))   # []  <-- kyun?!
Recall Solution

Ek map object ek one-pass iterator hai. Pehla list(result) ise end tak walk karta hai, [1, 4, 9] produce karta hai aur ise exhaust bhi kar deta hai. Doosre list(result) tak, iterator pehle hi end par khada hai jahan kuch nahi bacha — toh yeh [] yield karta hai. Fix: ek baar materialize karo aur reuse karo: squares = list(map(...)), phir squares ko do baar print karo.

Exercise 3.2

list(filter(lambda x: x, [0, 1, '', 'hi', None, [7], []])) kya return karta hai, aur kyun?

Recall Solution

Predicate sirf x hi hai, toh filter un items ko rakhta hai jinki truthiness True ho. Yaad karo falsy values: 0, '', None, [], False, 0.0.

  • 0 → falsy → drop
  • 1 → truthy → keep
  • '' → falsy → drop
  • 'hi' → truthy → keep
  • None → falsy → drop
  • [7] → non-empty list → truthy → keep
  • [] → empty list → falsy → drop

Result: [1, 'hi', [7]]. Yeh handy "falsy values strip karo" idiom hai.

Exercise 3.3

Predict karo aur explain karo:

list(map(lambda x: x * 2, filter(lambda x: x % 2 == 1, [1, 2, 3, 4, 5])))
Recall Solution

Inside-out padho — sabse andar wali call pehle chalti hai.

  1. filter(lambda x: x % 2 == 1, ...) odd numbers rakhta hai: [1, 3, 5].
  2. map(lambda x: x * 2, ...) har survivor ko double karta hai: 2, 6, 10.

Result: [2, 6, 10]. Order matter karta hai: pehle filter karna matlab map sirf 5 nahi, 3 items par kaam karta hai.

Exercise 3.4

Bug dhundo. Author squares ki list chahta tha lekin galat numbers mile (koi error nahi aayi) — silent bug explain karo aur fix karo:

nums = [1, 2, 3]
squares = list(map(lambda x: x^2, nums))   # expected [1, 4, 9]
Recall Solution

Yahan gotcha yeh hai ki Python mein ^ bitwise XOR hai, exponentiation nahi. Integers par XOR bilkul legal hai, isliye koi error nahi aata — code chalata hai aur silently galat values deta hai:

  • 1 ^ 2 = 3
  • 2 ^ 2 = 0
  • 3 ^ 2 = 1

Toh squares [1, 4, 9] ki jagah [3, 0, 1] ban jaata hai — ek silent logic bug, sabse khatarnak type, kyunki warn karne ke liye kuch crash nahi hota. Core lesson: Python mein power ** hai, ^ nahi. Fix: lambda x: x ** 2[1, 4, 9].


Level 4 — Synthesis

Exercise 4.1

Ek single pipeline banao jo words = ['cat', 'elephant', 'dog', 'hippopotamus', 'ox'] leta hai aur har us word ka uppercased version produce karta hai jo 3 letters se lambe hain. Ise likho, phir result do.

Recall Solution

Pehle filter karo (belt patli karo), phir map karo (survivors ko reshape karo):

words = ['cat', 'elephant', 'dog', 'hippopotamus', 'ox']
out = list(map(lambda w: w.upper(),
               filter(lambda w: len(w) > 3, words)))
  • filter un words ko rakhta hai jinka len > 3: ['elephant', 'hippopotamus'].
  • map har ek ko uppercase karta hai: ['ELEPHANT', 'HIPPOPOTAMUS'].

Result: ['ELEPHANT', 'HIPPOPOTAMUS'].

Exercise 4.2

Student records ki ek list ko score descending, phir name ascending as tie-breaker se sort karo. students = [('Ana', 88), ('Bo', 88), ('Cy', 91), ('Di', 75)]

Recall Solution

sorted tuples ko element by element compare karta hai. Hum score descending chahte hain lekin name ascending — opposite directions. Trick: numeric key ko negate karo taaki "bada score" "chota sort key" ban jaaye.

students = [('Ana', 88), ('Bo', 88), ('Cy', 91), ('Di', 75)]
out = sorted(students, key=lambda s: (-s[1], s[0]))

Keys computed: Ana→(-88,'Ana'), Bo→(-88,'Bo'), Cy→(-91,'Cy'), Di→(-75,'Di'). Un keys par ascending: Cy(-91), phir do -88 wale name se break hote hain (Ana before Bo), phir Di(-75).

Result: [('Cy', 91), ('Ana', 88), ('Bo', 88), ('Di', 75)].

Exercise 4.3

Given pairs = [(1, 3), (2, 2), (5, 1), (0, 9)], map + lambda use karke har pair ka product compute karo, phir 5 se bade products filter karo.

Recall Solution
pairs = [(1, 3), (2, 2), (5, 1), (0, 9)]
products = map(lambda p: p[0] * p[1], pairs)      # 3, 4, 5, 0
out = list(filter(lambda n: n > 5, products))
  • Products: 1*3=3, 2*2=4, 5*1=5, 0*9=0[3, 4, 5, 0].
  • > 5 rakhna: 3, 4, 5, 0 mein se koi bhi 5 se zyada nahi.

Result: [] (empty list). Note karo 5 > 5 False hai — ek classic off-by-boundary check.


Level 5 — Mastery

Exercise 5.1 — Infamous closure-in-a-loop bug

Yeh kya print karta hai, aur author ne shayad kya sochha tha?

funcs = [lambda: i for i in range(3)]
print([f() for f in funcs])
Recall Solution

Yeh [2, 2, 2] print karta hai, [0, 1, 2] nahi. Har lambda variable i par close karta hai, creation ke time par uski value par nahi. Jab tak hum functions ko call karte hain, loop khatam ho chuka hota hai aur i apni final value 2 par atka hota hai. Teeno lambdas ek hi i lookup karte hain. Fix — value ko abhi bind karo ek default argument se (definition ke time par evaluate hota hai):

funcs = [lambda i=i: i for i in range(3)]
print([f() for f in funcs])   # [0, 1, 2]

Yeh ek higher-order subtlety hai: functions names capture karte hain, aur lambdas koi exception nahi hain.

Exercise 5.2 — Laziness aur side effects

spy kitni baar print hoga, aur kyun?

def spy(x):
    print('seen', x)
    return x * 10
 
gen = map(spy, [1, 2, 3])
first = next(gen)      # EK value kheencho
print('first =', first)
Recall Solution

spy ek baar print karta hai (seen 1), phir first = 10. map lazy hai: next(gen) belt se exactly ek item kheenchta hai, toh spy sirf 1 ke liye chalta hai. Elements 2 aur 3 kabhi touch nahi hote kyunki humne unhe maanga hi nahi. Agar baad mein list(gen) karein, toh spy 2 aur 3 ke liye fire karta — aur note karo 1 pehle hi consume ho chuka hai, toh woh dobara nahi aayega. Full output:

seen 1
first = 10

Yeh demonstrate karta hai ki lazy iterators kaise kaam bachaa sakte hain — na liye gaye items par koi cost nahi.

Exercise 5.3 — Design judgement

Is lambda-heavy line ko zyada readably rewrite karo, aur bolo kab tum lambda rakhoge vs. def par switch karoge.

result = list(map(lambda x: 'even' if x % 2 == 0 else 'odd', range(4)))
Recall Solution

Pehle output: range(4) hai 0,1,2,3['even', 'odd', 'even', 'odd']. Ek ternary (a if cond else b) ek single expression hai, isliye lambda ke andar legal hai. Lekin ek list comprehension aam taur par zyada clear hoti hai:

result = ['even' if x % 2 == 0 else 'odd' for x in range(4)]

Rule of thumb: lambda tab rakhna jab rule chota ho aur tum ise function-taking tool ko de rahe ho (map/filter/sorted(key=...)). Named def par tab switch karo jab logic ko apni wajah batane ke liye ek naam chahiye, multiple statements ki zaroorat ho, ya reuse ho. Functions and def ka named def readability mein tab jeetta hai jab "cleverness cost" "one-liner benefit" se zyada ho.


Recall Final mixed drill (paancho predict karo, phir reveal karo)
  1. list(map(lambda x: x + 1, [0, 9])) ::: [1, 10]
  2. list(filter(lambda x: x, [0, 2, '', 'a'])) ::: [2, 'a']
  3. sorted([-3, 1, -2], key=lambda x: abs(x)) ::: [1, -2, -3]
  4. list(map(lambda a, b: a * b, [2, 3], [4, 5])) ::: [8, 15]
  5. (lambda: 7)() ::: 7

Connections

  • Functions and def — lambda ko named function mein kab graduate karein.
  • First-class functions — kyun ek lambda store, pass, aur return kiya ja sakta hai.
  • List comprehensionsmap/filter pipelines ka readable alternative.
  • Iterators and lazy evaluation — one-pass aur side-effect exercises ki jadd.
  • sorted and key functions — upar wale key= exercises.
  • Higher-order functions — L5 mein closure-capture behaviour.