Home › Hindi › Generator Hindi में
Python Generator — एक-एक item देने वाले functions
🌐 यह page Hindi में है · Read the English guide →
yieldLazy evaluationMemoryInfinite sequences
yield function को generator बना देता है
Function के अंदर return की जगह yield लिख दो और वो सादा function नहीं रहता — वो generator बन जाता है। फर्क सिर्फ शब्द का नहीं, चलने के तरीके का है।
def countdown(n):
print("शुरू")
while n > 0:
yield n # यहाँ रुकता है, value देता है
n -= 1
print("खत्म")
g = countdown(3)
print(type(g)) #
print(g) #
# अब तक एक भी line चली नहीं! 'शुरू' तक print नहीं हुआ।
print(next(g)) # शुरू \n 3
print(next(g)) # 2
print(next(g)) # 1
print(next(g)) # खत्म \n StopIteration दो बातें यहाँ सबसे ज़रूरी हैं। पहली — countdown(3) call करने पर function चलता ही नहीं; सिर्फ एक generator object बनता है। दूसरी — yield पर पहुँचकर function वहीं रुक जाता है, सारी local state के साथ, और अगले next() पर वहीं से आगे बढ़ता है।
Lazy evaluation — memory क्यों बचती है
यही generator का असली फायदा है। List सारी values एक साथ memory में बनाती है; generator एक समय में एक value रखता है।
import sys
# एक करोड़ squares
big_list = [x * x for x in range(10**7)]
print(sys.getsizeof(big_list)) # लगभग 84 MB
big_gen = (x * x for x in range(10**7))
print(sys.getsizeof(big_gen)) # लगभग 200 bytes
# दोनों का total एक ही आएगा
print(sum(big_gen)) # और list कभी बनी ही नहीं200 bytes बनाम 84 MB — यही फर्क तय करता है कि आपका script चलेगा या memory खत्म हो जाएगी। ध्यान रहे कि getsizeof सिर्फ generator object का आकार बताता है, क्योंकि उसमें सचमुच लगभग कुछ है ही नहीं।
Infinite sequences — list से नामुमकिन
Generator कभी खत्म न होने वाली sequences बना सकता है, क्योंकि वो कभी सब कुछ एक साथ नहीं बनाता:
def naturals():
n = 1
while True: # infinite loop, पर चलेगा
yield n
n += 1
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
def evens():
yield from naturals() # एक generator से दूसरे में
# itertools के साथ use करो — ये कभी रुकेंगे नहीं, तो slice चाहिए
import itertools
print(list(itertools.islice(fibonacci(), 10)))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
first_big = next(x for x in naturals() if x > 1000) # 1001, बिना 1000 items बनाएआखिरी line generator की ताकत दिखाती है: हज़ारवाँ item चाहिए था, तो सिर्फ हज़ार तक गिना गया — list comprehension में पहले सारे items memory में बन जाते।
Generator expression और comprehension
Bracket बदलने से list comprehension generator expression बन जाता है। बस इतना फर्क, पर नतीजा बड़ा है:
[x * x for x in range(10**7)] # list — तुरंत सब बन जाता है
(x * x for x in range(10**7)) # generator — lazy
# सबसे ज़्यादा काम का use: तुरंत consume हो जाने वाली जगह
sum(x * x for x in rows) # parentheses की ज़रूरत भी नहीं
max(len(n) for n in names)
any(n < 0 for n in nums)
all(v > 0 for v in values)
"\n".join(str(r) for r in rows)नियम आसान है: नतीजा एक बार ही पढ़ना है और किसी sum/max/any/join में जाना है, तो generator लिखो। नतीजे को बाद में दोबारा पढ़ना है, index करना है, या len() चाहिए, तो list चाहिए।
Generator एक बार ही चलता है
यह सबसे आम गलती है, और चुपचाप गलत नतीजा देती है — कोई error नहीं:
gen = (x * x for x in range(5))
print(list(gen)) # [0, 1, 4, 9, 16]
print(list(gen)) # [] — खत्म हो चुका है, दोबारा कुछ नहीं
print(sum(gen)) # 0 — कोई error नहीं, बस गलत जवाब
# दोबारा चाहिए तो दोबारा बनाओ
gen = (x * x for x in range(5))
print(list(gen)) # [0, 1, 4, 9, 16]
# या बार-बार use करना है तो list बना लो
vals = [x * x for x in range(5)]
print(list(vals), list(vals)) # दोनों बार भरा हुआइसीलिए दो जगह iterate करना हो तो list बना लो। Generator को बार-बार पढ़ने की कोशिश करना बहुत भ्रमित करने वाला bug है, क्योंकि code बिना शिकायत के चुपचाप खाली नतीजा देता रहता है।
कब generator चुनें, कब list
- Generator चुनो — data बड़ा या infinite हो, नतीजा एक बार ही पढ़ना हो, बड़ी file लाइन-दर-लाइन पढ़नी हो, या pipeline बनानी हो।
- List चुनो —
len()चाहिए, index से पहुँचना है, दोबारा iterate करना है, sort करना है, या data छोटा है। - दोनों — छोटे data पर फर्क नगण्य है, तो जो पढ़ने में साफ हो वही लिखो।
# generator pipeline — हर step lazy
def read_rows(path):
with open(path) as f:
for line in f:
yield line.strip()
def parse(lines):
for line in lines:
if line:
yield line.split(",")
def keep_valid(rows):
for row in rows:
if len(row) == 3:
yield row
rows = keep_valid(parse(read_rows("big.csv"))) # अब तक कुछ पढ़ा ही नहीं
first = next(rows) # पहली valid row — एक लाइन पढ़ीयह pattern असली data processing में बहुत काम आता है। एक करोड़ लाइन की CSV हो तो भी memory में एक समय में एक लाइन रहती है।
आम गलतियाँ
- Generator को दोबारा iterate करना। दूसरी बार चुपचाप खाली मिलेगा — कोई error नहीं।
len()माँगना। Generator परTypeErrorमिलेगा, क्योंकि उसकी लंबाई तय नहीं।returnकोyieldसमझ लेना।returngenerator मेंStopIterationका संकेत देता है, value बाहर नहीं देता।yieldको list में wrap करना।list(my_gen())सारी lazy benefit मिटा देता है — memory वहीं वापस आ जाती है।- Side effect वाले generator पर भरोसा। Consumer कितना पढ़ेगा, उस पर निर्भर करेगा कि कितना side effect होगा — debug करना बहुत मुश्किल।
gen = (x for x in range(3))
len(gen) # TypeError: object of type 'generator' has no len()
gen[0] # TypeError: 'generator' object is not subscriptable
list(gen) # ✅ [0, 1, 2] — index चाहिए तो पहले list बनाओ
🛠️ Practice करो (free, browser में)
पढ़ना काफी नहीं — यही bug खुद fix करके देखो। नीचे के problems browser में ही चलते हैं, कोई install नहीं, कोई login नहीं।
- Function returning nothing — return और yield का फर्क।
अक्सर पूछे जाने वाले सवाल
Generator क्या है?
एक ऐसा function जिसमें yield होता है। वो सारी values एक साथ नहीं बनाता — हर next() पर एक value देता है और वहीं रुक जाता है, सारी local state के साथ। इसलिए memory लगभग नहीं लगती।
yield और return में क्या फर्क है?
return function को खत्म कर देता है और एक value देता है। yield function को वहीं रोकता है, value देता है, और अगले next() पर वहीं से आगे बढ़ने देता है। Generator में return StopIteration का संकेत देता है।
Generator से memory कितनी बचती है?
बहुत। एक करोड़ squares की list लगभग 84 MB लेती है; वही generator expression लगभग 200 bytes, क्योंकि उसमें एक समय में एक value रहती है। बड़े data पर यही फर्क तय करता है कि script चलेगी या नहीं।
क्या generator को दोबारा use कर सकते हैं?
नहीं। वो एक बार ही चलता है और खत्म होने पर चुपचाप खाली नतीजा देता है — कोई error नहीं। दोबारा चाहिए तो दोबारा बनाओ, या बार-बार use करना हो तो list बना लो।
Generator expression और list comprehension में क्या फर्क है?
Bracket बनाम parentheses। [x for x in data] तुरंत पूरी list memory में बनाता है; (x for x in data) lazy generator देता है। नतीजा एक बार ही पढ़ना हो तो generator बेहतर है।