Worked examples — Variable scope — LEGB rule (Local, Enclosing, Global, Built-in)
1.2.30 · D3· Coding › Introduction to Programming (Python) › Variable scope — LEGB rule (Local, Enclosing, Global, Built-
Shuru karne se pehle, ek shared mental picture. Har "scope" sirf ek labelled box hai jo names hold karta hai. Jab Python koi name padhta hai, woh in boxes ko ek fixed order mein walk karta hai aur pehla box grab karta hai jiske paas woh name hai.

- L = woh box jo jis moment function run karna shuru karta hai create hota hai.
- E = us function ka box jo current function ko wrap karta hai.
- G = poori file (module) ke liye box.
- B = ek permanent box jo Python ke saath aata hai (
len,print,range,sum, …).
Yeh picture open rakho. Neeche har example sirf "kaun sa box jeet ta hai, aur kyun" hai.
The scenario matrix
Variable scope mein thode se axes hain jo fully determine karte hain kya hoga. Har real program in cells ka combination hota hai.
| Axis | Cases jo hume cover karne hain |
|---|---|
| Operation | pure read · write bina keyword ke · write with global · write with nonlocal |
| Kaun sa box read jeeeta hai | L mein mila · E mein mila · G mein mila · B mein mila · kahin nahi mila (NameError) |
| The assignment trap | read-before-write us name ki jo assignment ne local banaya (UnboundLocalError) |
| Shadowing | L/E/G mein ek name ek built-in (B) ko hide karta hai |
| Degenerate / zero cases | function jo kuch assign nahi karta · empty enclosing scope · nonlocal bina target ke · ek name delete karna |
| Mutation vs rebinding | list ka contents change karna (scope keyword ki zaroorat nahi) vs name ko new list pe point karna (global/nonlocal chahiye) |
| Real-world twist | ek counter jo calls ke across share hota hai (closure) |
| Exam twist | loop/if blocks scope nahi banate; comprehensions banate hain |
Neeche, har example us cell(s) ke saath tagged hai jo woh cover karta hai. End tak, upar ka har cell ticked ho jayega.
Example 1 — Read har box mein baari baari resolve hota hai
Steps
inner()run karo. Python koprintke liyetagread karna hai. Yeh step kyun?print(tag)ek read hai, toh L→E→G→B walk shuru hoti hai.- L mein dekho (inner ka box).
tag = "L-inner"wahan hai → ruko. Yeh step kyun? Pehla match jeet ta hai; Python kabhi E ya G nahi kholega. - Result:
"L-inner".
Ab inner se tag = "L-inner" delete karo. Read empty L box se past E mein walk karta hai aur "E-outer" paata hai. Woh bhi delete karo, aur yeh G mein walk karta hai aur "G-file" paata hai.
Verify: teeno lines present hone par →
L-inner. L hatane par →E-outer. L aur E hatane par →G-file.

Example 2 — Built-in tak poora fall karna
Steps
count_charske andar,lenread karo. Yeh L mein nahi hai (sirfwordhai), E mein nahi (koi enclosing function nahi), G mein nahi (file koilendefine nahi karti). Yeh step kyun? Hume B se pehle L, E, G exhaust karna padega — yahi poora order hai.- B mein mila →
lenPython ka built-in string length function hai.len("hi")=2. Yeh step kyun? Yahi reason hai kilen,print,rangebina import kiye kaam karte hain: yeh permanently B mein rehte hain. - Ab
print(banana).bananaread karo: L, E, G, ya B mein nahi. Yeh step kyun? Jab charon boxes fail ho jaate hain, toh try karne ke liye kuch nahi bachta. - Python
NameError: name 'banana' is not definedraise karta hai.
Verify:
len("hi")=2.bananahar jagah undefined hai →NameError.
Example 3 — The assignment trap (UnboundLocalError)
Steps
- Compile time par (function ke kabhi run karne se pehle), Python
add_tipscan karta hai aurtotal = …dekhta hai. Yeh step kyun? Kisi name ke bare assignment se woh poori function body ke liye Local flag ho jaata hai — ek baar decide hota hai, pehle se, line by line nahi. - Toh
totalpooreadd_tipmein ek local name hai. Globaltotal = 100ab andar invisible hai. Yeh step kyun? Local-creation rule us specific name ke liye L→E→G walk ko override karta hai. total + 10execute karo. Right-hand side compute karne ke liye hume localtotalread karna hoga — lekin abhi tak uski koi value nahi hai (assignment abhi complete nahi hui). Yeh step kyun? Read write complete hone se pehle hota hai, aur fall back karne ke liye koi doosratotalnahi hai.- Python
UnboundLocalError: local variable 'total' referenced before assignmentraise karta hai.

Verify:
add_tip()call karne parUnboundLocalErroraata hai, kabhi110return nahi karta.
Example 4 — global se fix karna
Steps
global totalPython ko batata hai: "is function ke liye,totalG name hai — local mat banao." Yeh step kyun? Yeh Example 3 ke compile-time local-creation rule ko cancel kar deta hai.- Ab
total + 10global100padhta hai →110, aur assignment global ko110se rebind karti hai. Yeh step kyun? Local rule gone hone se, read aur write dono same G box pe point karte hain. add_tip()110return karta hai; baad mein module-leveltotalbhi110hai.
Verify:
add_tip()=110, aur globaltotal=110baad mein.
Example 5 — nonlocal se enclosing state fix karna
Steps
make_counter()run hota hai, apne box meinn = 0create karta hai,stepdefine karta hai,stepreturn karta hai (useckaho). Yeh step kyun?make_counterfinish hone ke baad bhi, uskanbox survive karta hai kyunkistepabhi bhi usse point kar raha hai — yahi ek closure hai.- Pehla
c():nonlocal nname ko nearest enclosing box (E) pe aim karta hai, L pe nahi, G pe nahi. Yeh step kyun?nonlocalke bina,n += 1ek fresh localnbanana try karta aur bilkul Example 3 ki tarahUnboundLocalErrordeta. n += 1E ka0padhta hai,1write back karta hai,1return karta hai. Doosra call →2. Teesra →3.
Verify:
c(), c(), c()(1, 2, 3)deta hai.
Example 6 — Built-in ko shadow karna
Steps
- Line 1:
sumread karo → G mein abhi nahi → B mein mila (built-in) →sum([1,2,3])=6. Yeh step kyun? Shadowing se pehle, B hi jagah hai jahansumrehta hai. sum = 10G box meinsumname daalta hai. Yeh step kyun? Ab L→E→G→B walksumG mein B tak pahunchne se pehle paata hai — built-in hidden hai, delete nahi.sum + 5G kasum=10padhta hai →15.sum([1,2,3])G kasum=10padhta hai, phir10(...)call karne ki koshish karta hai. Yeh step kyun? Ek integer callable nahi hai →TypeError.
Verify: original
sum([1,2,3])=6; shadowing ke baad,sum + 5=15;sum([1,2,3])TypeErrorraise karta hai.
Example 7 — Mutation ke liye koi keyword nahi chahiye
Steps
add_book:shelf.append(3)shelfka ek read hai (list dhundhne ke liye), phir ek method call jo use in place mutate karta hai. Yeh step kyun? Yahan koi assignmentshelf = …nahi hai, toh local-creation rule kabhi fire nahi hota. Read L→E→G walk karta hai, list paata hai, aur.appendusi object ko edit karta hai →[1, 2, 3]. Dekho Mutable vs Immutable arguments.replace_shelf:shelf = [9, 9]ek assignment hai →shelfus function ka local hai. Yeh step kyun? Yeh local box mein ek brand-new list banata hai aur function end hone par usse throw away kar deta hai; global list untouched rehti hai.- Final global
shelf=[1, 2, 3].
Verify: dono calls ke baad,
shelf=[1, 2, 3].
Example 8 — Degenerate nonlocal bina target ke
Steps
nonlocal mek enclosing function ke box meinmvariable demand karta hai. Yeh step kyun?nonlocalsirf ek existing E name ko reuse karta hai; woh ek naya create nahi kar sakta.outerke body mein kahin bhimnahi hai → koi E target nahi hai. Yeh step kyun? Yeh empty-enclosing-scope degenerate case hai.- Python ise compile time par reject karta hai:
SyntaxError: no binding for nonlocal 'm' found.
Verify: code ek
SyntaxErrorhai (compile-time),NameError/UnboundLocalErrornahi.
Example 9 — Exam twist: blocks scope nahi banate, comprehensions banate hain
Steps
if/forblocks Python mein koi naya box nahi banate.msgreportke single local box mein rehta hai. Yeh step kyun? C ya Java ke unlike, Python sirf function, module, aur comprehension se scope karta hai —{}/indentation blocks se nahi.report(True):ifrun hota hai,msg = "yes"local box fill karta hai →yesprint hota hai.report(False):ifskip ho jaata hai, tohmsgkabhi assign nahi hua → use padhna →UnboundLocalError. Yeh step kyun? Example 3 jaisa hi trap: assignment use local mark karta hai, lekin is run ne kabhi write execute nahi ki.- Comprehension
[k*k for k in range(4)][0, 1, 4, 9]deta hai, aur uska loop variablekapna box pata hai. Yeh step kyun? Comprehensions teen scope-makers mein se ek hain, tohkmodule mein leak nahi hota. - Module level par
print(k)→NameError, kyunkikG mein kabhi exist nahi kiya.
Verify:
report(True)→yes;report(False)→UnboundLocalError;[k*k for k in range(4)]=[0,1,4,9]; module-levelprint(k)→NameError.
Active Recall
Recall Scenarios par self-test
- Example 3 mein, Python kab decide karta hai ki
totallocal hai — compile time ya run time? shelf.append(3)koglobalki zaroorat kyun nahi, lekinshelf = [9,9]ko hogi?- Kaun sa error class ek
nonlocalbina enclosing target ke raise karta hai, aur kab? report(False)crash kyun karta hai jabkireport(True)theek hai?sum = 10ke baad,sum([1,2,3])NameErrorki jagahTypeErrorkyun deta hai?
Connections
- Parent topic (Hinglish) — core LEGB rule jise yeh examples exercise karti hain.
- Functions and Parameters — har call hi hai jo L box create karta hai.
- Closures and Nested Functions — Example 5 ka counter E ke upar ek live closure hai.
- Namespaces and the dict model — yahan har box actually ek dictionary hai.
- Mutable vs Immutable arguments — Example 7 mutate-vs-rebind distinction hai.
- NameError and UnboundLocalError — upar catalogue kiye gaye do crashes.
- Modules and import — G box populate karta hai jise Examples 4, 6, 7 read karte hain.