🔐
Iterators & Closures

Closures

Functions Jo State Yaad Rakhte Hain
💡 Closure ek function hai jiske paas apni khud ki "memory" hai — jaise ek backpack jo function apne saath le jaata hai, jisme uske "birth place" (jaha define hua tha) ki kuch cheezein packed hain, chahe wo jagah (outer function) kabhi ki khatam ho chuki ho.

Closure tab banta hai jab ek inner function apne outer (enclosing) function ki variables ko "remember" karta hai, chahe outer function ka execution khatam ho chuka ho. Ye decorators ka bhi foundation hai (jo humne pehle dekha).

Closures useful hain jab tumhe "function factories" chahiye — functions jo customized versions of themselves return karte hain, based on kuch initial configuration.

def make_multiplier(factor):
    def multiplier(x):
        return x * factor   # 'factor' outer function se "remembered" hai
    return multiplier

double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))   # 10 — factor=2 yaad hai
print(triple(5))    # 15 — factor=3 yaad hai (alag closure!)

# make_multiplier already khatam ho chuka hai, phir bhi 'factor' zinda hai
# har closure ka apna independent 'factor' hai
🔐
Closure ek function hai jiske paas apni khud ki "memory" hai — jaise ek backpack jo function apne saath le jaata hai, jisme uske "birth place" (jaha define hua tha) ki kuch cheezein packed hain, chahe wo jagah (outer function) kabhi ki khatam ho chuki ho.
1 / 2
⚡ Quick Recap
  • Closure = inner function jo outer ki variables remember karta hai
  • Outer function khatam hone ke baad bhi variable zinda rehta hai
  • Function factories aur decorators ka foundation
On this page (2 subtopics)

Closure ke andar se outer variable ko sirf READ kar sakte ho by default — modify karne ke liye nonlocal keyword zaroori hai (global keyword jaisa hi concept, lekin enclosing function scope ke liye, module-level ke liye nahi).

def make_counter():
    count = 0
    def increment():
        nonlocal count   # bina iske, count += 1 error dega
        count += 1
        return count
    return increment

counter = make_counter()
print(counter())   # 1
print(counter())   # 2
print(counter())   # 3 — state persist hoti hai calls ke beech
⚠️Common Mistake: nonlocal ke bina, count += 1 ek "UnboundLocalError" dega — Python assumption karta hai ki count += 1 ek NAYI local variable bana raha hai, existing outer wali ko access nahi kar raha.

Simple state (ek-do variables) ke liye closures concise hain. Complex state (multiple related variables + methods) ke liye classes zyada readable/maintainable hain — "counter with just increment" closure ke liye theek hai, "BankAccount with balance, history, methods" class ke liye better hai.

# Closure — simple case:
def make_counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

# Class — complex case, better fit:
class Counter:
    def __init__(self):
        self.count = 0
    def increment(self):
        self.count += 1
        return self.count
    def reset(self):
        self.count = 0
💡Tip: Rule of thumb: agar tumhe sirf ek function chahiye jo state remember kare, closure use karo. Agar multiple related operations aur state chahiye, class use karo.