जेनरेटर्स पायथन में एक शक्तिशाली फीचर हैं (PEP 255 से) जो मेमोरी-कुशल इटरेशन सक्षम करते हैं।
जेनरेटर क्या है?
defकीवर्ड से परिभाषित फ़ंक्शन जिसमेंyieldहो।returnके बजायyieldमान लौटाता है।- कॉल करने पर जेनरेटर ऑब्जेक्ट (इटरेटर) लौटाता है।
- राज्य (लोकल वेरिएबल्स)
yieldपर सस्पेंड होता है और अगले कॉल पर रिज्यूम होता है।
बुनियादी उदाहरण
def generator_thru_iter():
yield 'xyz'
yield 246
yield 40.50
# for लूप के साथ (इटरेटर प्रोटोकॉल)
for i in generator_thru_iter():
print(i)
# xyz
# 246
# 40.5
# next() के साथ मैन्युअल
g = generator_thru_iter()
print(next(g)) # xyz
print(next(g)) # 246
print(next(g)) # 40.5
print(next(g)) # StopIteration अपवाद
जेनरेटर vs नॉर्मल फ़ंक्शन
| नॉर्मल फ़ंक्शन | जेनरेटर |
|---|---|
| सभी मान एक साथ कंप्यूट करके लिस्ट लौटाता है | एक समय में एक मान yield करता है |
| सभी मान मेमोरी में स्टोर होते हैं | लेज़ी इवैल्यूएशन: कम मेमोरी |
return से समाप्त | yield से सस्पेंड, अंत में StopIteration |
| कॉल पर निष्पादित होता है | कॉल पर जेनरेटर ऑब्जेक्ट लौटाता है, इटरेशन पर निष्पादित |
व्यावहारिक उदाहरण: बड़े नंबर्स के वर्ग
समस्या: 1 से 200 बिलियन तक के वर्ग प्रिंट करना - लिस्ट बनाने से मेमोरी ओवरफ्लो।
बिना जेनरेटर (खराब)
n = 200000000000
number_list = range(1, n+1) # विशाल रेंज ऑब्जेक्ट (पायथन 3 में OK, लेकिन...)
for i in number_list:
print(i * i) # फिर भी धीमा
जेनरेटर के साथ (अच्छा)
def num_generator(n):
num = 1
while True:
yield num
if num == n:
return
num += 1
for i in num_generator(200000000000):
print(i * i)
# एक समय में एक मान, O(1) मेमोरी
कैसे काम करता है
forलूप जेनरेटर को कॉल करता है →num_generatorचलना शुरू करता है।yield numपर रुकता है, मान लौटाता है, स्टेट फ्रीज होता है।- लूप बॉडी चलती है (
print(i*i))। - अगली इटरेशन पर
next()कॉल होता है →yieldके बाद से जारी रहता है। num == nहोने परreturn→StopIterationउठता है, लूप समाप्त।
जेनरेटर एक्सप्रेशन्स
लिस्ट कॉम्प्रिहेंशन जैसा सिंटैक्स लेकिन पैरेंथेसिस के साथ:
# लिस्ट कॉम्प्रिहेंशन (सभी मेमोरी में)
squares_list = [x*x for x in range(10)]
# जेनरेटर एक्सप्रेशन (लेज़ी)
squares_gen = (x*x for x in range(10))
print(next(squares_gen)) # 0
print(next(squares_gen)) # 1
उन्नत: yield from (पायथन 3.3+)
def gen1():
yield 1
yield 2
def gen2():
yield from gen1()
yield 3
print(list(gen2())) # [1, 2, 3]
कब उपयोग करें
- बड़े/अनंत सीक्वेंसेज़।
- पाइपलाइन प्रोसेसिंग (डेटा स्ट्रीमिंग)।
- मेमोरी-क्रिटिकल एप्लिकेशन्स।
- कॉरूटाइन्स/असिंक्रोनस प्रोग्रामिंग का आधार।