def count_up(n): i = 0 while i < n: yield i # pause here, hand out i i += 1 # resume here next timeg = count_up(3) # NOTHING runs yet; g is a generator objectprint(next(g)) # 0 <- runs until first yield, pausesprint(next(g)) # 1 <- resumes after yield, runs to next yieldprint(next(g)) # 2print(next(g)) # raises StopIteration (loop ended)
Tum ek plain class se generator ka concept build kar sakte ho, jo prove karta hai ki isme koi magic nahi hai:
class CountUp: def __init__(self, n): self.n = n self.i = 0 def __iter__(self): return self def __next__(self): if self.i >= self.n: raise StopIteration # the "end of body" val = self.i # the "yield value" self.i += 1 # the "resume" bookkeeping return val
Toh ek generator exactly yeh hai: ek object jisme __iter__ aur __next__ hain, lekin position ka saving interpreter karta hai, tum nahi.
Ek kahani sunane wale ki kalpana karo jo tumhe EK sentence sunata hai, phir bich mein freeze ho jaata hai aur wait karta hai. Jab tum "next!" bolte ho, woh exactly wahi word se continue karta hai jahan ruka tha — woh kabhi nahi bhoolta kahan tha. Yahi ek generator hai: yield hai freeze, next() hai tumhara "next!", aur send() hai tumhara woh word whisper karna jo woh decide karne ke liye use karta hai ki aage kya bolna hai. Kyunki woh ek time par ek hi sentence bolta hai, use poori kitaab dimag mein rakhne ki zaroorat nahi — isliye memory bachti hai.
What does calling a generator function actually do?
Turant ek generator object return karta hai; body sirf pehle next() par chalti hai.
What does next(g) do?
Execution ko next yield tak resume karta hai (woh value return karta hai) ya agar body khatam ho jaaye toh StopIteration raise karta hai.
Difference between yield and return?
yield pause karta hai aur state save karta hai taaki baad mein resume ho sake; return function khatam kar deta hai (generator mein yeh StopIteration raise karta hai).
Why are generators memory-efficient?
Yeh demand par lazily values produce karte hain, poori sequence build/store karne ki jagah.
Can you iterate a generator twice?
Nahi — yeh single-use hai; ek baar exhaust hone ke baad kuch nahi yield karta.
What does g.send(v) do?
Generator ko resume karta hai, paused yield expression ko v evaluate karata hai, aur next yielded value return karta hai.
Why must you prime a generator before send(non-None)?
Woh kisi bhi yield tak pahuncha nahi hai, toh koi paused yield expression nahi hai jo value receive kare; warna TypeError.
next(g) is equivalent to which send call?
g.send(None).
What does yield from iterable do?
Sub-iterable ki har value yield karta hai aur send/exceptions forward karta hai aur uski return value capture karta hai.
How does a for loop know when to stop on a generator?
Woh __next__ ke zariye raise hone wale StopIteration ko catch karta hai aur silently band ho jaata hai.