🧭
Iterators & Closures

Iterators & the Iterator Protocol

__iter__, __next__
💡 Iterator ek bookmark hai jo kisi bhi book (collection) ke through navigate karne deta hai — for loop internally isi bookmark ko baar-baar "agla page do" bolta rehta hai, jab tak book khatam na ho jaaye.

"Iterable" koi bhi object hai jispar for loop chal sakta hai (list, string, dict). "Iterator" wo object hai jo actually values produce karta hai, ek time par ek — __next__() call hone par agli value deta hai, ya StopIteration raise karta hai jab khatam ho jaaye.

iter() function kisi iterable se ek iterator banata hai. next() function iterator se agli value nikalta hai. for loop internally exactly yehi karta hai — automatically, tumhare liye.

nums = [1, 2, 3]
it = iter(nums)          # iterator banao

print(next(it))   # 1
print(next(it))   # 2
print(next(it))   # 3
# print(next(it)) # StopIteration error — khatam ho gaya

# for loop internally ye hi karta hai:
for n in nums:
    print(n)
# yehi hai: it = iter(nums); while True: try: n = next(it) except StopIteration: break
🧭
Iterator ek bookmark hai jo kisi bhi book (collection) ke through navigate karne deta hai — for loop internally isi bookmark ko baar-baar "agla page do" bolta rehta hai, jab tak book khatam na ho jaaye.
1 / 6
⚡ Quick Recap
  • Iterable = for loop mein use ho sakta hai (list, dict, string)
  • Iterator = actual values produce karta hai, __next__() se
  • for loop internally iter()/next() hi use karta hai
On this page (2 subtopics)

Apni khud ki class ko iterable/iterator banane ke liye __iter__ aur __next__ dunder methods implement karo — poora control milta hai custom iteration logic par.

class CountUp:
    def __init__(self, max_val):
        self.max_val = max_val
        self.current = 0

    def __iter__(self):
        return self   # khud hi iterator hai

    def __next__(self):
        if self.current >= self.max_val:
            raise StopIteration
        self.current += 1
        return self.current

for num in CountUp(5):
    print(num)   # 1 2 3 4 5
💡Tip: Simple cases ke liye generator function (yield wala) likhna usually easier hai poori class banane se — class-based iterators sirf tab zaroori hain jab extra state/methods chahiye hon.

Kuch iterators (jaise itertools.count()) infinite hote hain — kabhi StopIteration nahi dete. Loop mein use karte waqt explicit break condition zaroori hai, warna infinite loop ban jaayega.

from itertools import count

for num in count(start=1):
    print(num)
    if num >= 5:
        break   # ZAROORI — warna infinite chalega
⚠️Common Mistake: itertools.count() jaisa infinite iterator bina break ke for loop mein use karna program ko hang kar dega — hamesha ek termination condition rakho.