आप पायथन जनरेटर कार्यों के लिए क्या उपयोग कर सकते हैं?


213

मैं पायथन सीखना शुरू कर रहा हूं और मैं जनरेटर फंक्शंस में आया हूं, जो उन में उपज का बयान है। मैं जानना चाहता हूं कि इन कार्यों को हल करने में किस प्रकार की समस्याएं हैं।


6
शायद एक बेहतर सवाल यह होगा कि हमें
बजे

जवाबों:


239

जनरेटर आपको आलसी मूल्यांकन देते हैं। आप उन पर पुनरावृत्ति करके उनका उपयोग करते हैं, या तो स्पष्ट रूप से 'के लिए' के ​​साथ या किसी भी फ़ंक्शन को पास करके या उस आंकड़े का निर्माण करके। आप कई वस्तुओं को वापस करने के रूप में जनरेटर के बारे में सोच सकते हैं, जैसे कि वे एक सूची लौटाते हैं, लेकिन एक बार में उन सभी को एक-एक करके वापस करने के बजाय, और अगले फ़ंक्शन का अनुरोध होने तक जनरेटर फ़ंक्शन को रोक दिया जाता है।

जेनरेटर परिणामों के बड़े सेटों की गणना करने के लिए अच्छे हैं (विशेष रूप से स्वयं को शामिल करने वाली गणनाओं में) जहां आप नहीं जानते कि क्या आपको सभी परिणामों की आवश्यकता है, या जहां आप एक ही समय में सभी परिणामों के लिए मेमोरी आवंटित नहीं करना चाहते हैं । या ऐसी स्थितियों के लिए जहां जनरेटर किसी अन्य जनरेटर का उपयोग करता है , या किसी अन्य संसाधन का उपभोग करता है, और यह अधिक सुविधाजनक है यदि ऐसा हुआ है जितनी देर हो सके।

जनरेटर के लिए एक और उपयोग (जो वास्तव में एक ही है) पुनरावृत्ति के साथ कॉलबैक को बदलने के लिए है। कुछ स्थितियों में आप बहुत सारे काम करना चाहते हैं और कभी-कभी फोन करने वाले को वापस रिपोर्ट करते हैं। परंपरागत रूप से आप इसके लिए कॉलबैक फ़ंक्शन का उपयोग करेंगे। आप इस कॉलबैक को कार्य-कार्य में पास करते हैं और यह समय-समय पर इस कॉलबैक को कॉल करेगा। जनरेटर दृष्टिकोण यह है कि कार्य-फ़ंक्शन (अब एक जनरेटर) कॉलबैक के बारे में कुछ भी नहीं जानता है, और जब भी यह कुछ रिपोर्ट करना चाहता है, तो केवल उपज देता है। कॉल करने वाला, एक अलग कॉलबैक लिखने और काम-फ़ंक्शन को पास करने के बजाय, जनरेटर के चारों ओर 'लूप' के लिए सभी रिपोर्टिंग काम करता है।

उदाहरण के लिए, मान लें कि आपने 'फाइलसिस्टम सर्च' प्रोग्राम लिखा है। आप खोज को उसकी संपूर्णता में कर सकते हैं, परिणाम एकत्र कर सकते हैं और फिर उन्हें एक बार में प्रदर्शित कर सकते हैं। पहले दिखाए जाने से पहले सभी परिणामों को एकत्रित करना होगा, और सभी परिणाम एक ही समय में मेमोरी में होंगे। या आप उन्हें खोजने के दौरान परिणाम प्रदर्शित कर सकते हैं, जो कि अधिक स्मृति कुशल और उपयोगकर्ता के प्रति अधिक मित्रता होगी। बाद के परिणाम को प्रिंटिंग-फंक्शन को फाइलसिस्टम-सर्च फंक्शन में पास किया जा सकता है, या यह केवल सर्च फंक्शन को एक जनरेटर बनाकर और परिणाम पर पुनरावृति करके किया जा सकता है।

यदि आप बाद के दो दृष्टिकोणों का उदाहरण देखना चाहते हैं, तो os.path.walk () (कॉलबैक के साथ पुराना फाइल सिस्टम-वॉकिंग फंक्शन) और os.walk () (नया फाइलसिस्टम-वॉकिंग जनरेटर) देखें। आप वास्तव में एक सूची में सभी परिणामों को इकट्ठा करना चाहते थे, जेनरेटर दृष्टिकोण बड़ी सूची के दृष्टिकोण में बदलने के लिए तुच्छ है:

big_list = list(the_generator)

क्या एक जनरेटर जैसे कि फाइलसिस्टम सूचियों का निर्माण एक कोड के समानांतर क्रिया करता है जो उस जनरेटर को लूप में चलाता है? आदर्श रूप से कंप्यूटर लूप के शरीर को चलाएगा (अंतिम परिणाम को संसाधित करते हुए) समवर्ती करते हुए जो कुछ भी जनरेटर को अगले मूल्य प्राप्त करने के लिए करना होगा।
स्टीवन लू

@StevenLu: जब तक यह मैन्युअल रूप से थ्रेड को लॉन्च करने से पहले yieldऔर joinउनके बाद अगले परिणाम प्राप्त करने के लिए मुसीबत में जाता है , यह समानांतर में निष्पादित नहीं करता है (और कोई मानक पुस्तकालय जनरेटर ऐसा नहीं करता है; चुपके से थ्रेड लॉन्च करना) पर फेंक दिया जाता है। जनरेटर yieldअगले मूल्य का अनुरोध किए जाने तक प्रत्येक पर रुकता है। यदि जेनरेटर I / O को लपेट रहा है, तो OS इस अनुमान पर फ़ाइल से डेटा को कैशिंग कर सकता है कि इसे शीघ्र ही अनुरोध किया जाएगा, लेकिन यह OS, Python शामिल नहीं है।
शैडो रेंजर

90

जनरेटर का उपयोग करने का एक कारण कुछ प्रकार के समाधानों के लिए समाधान को स्पष्ट करना है।

दूसरा एक समय में परिणामों का इलाज करना है, परिणामों की विशाल सूचियों के निर्माण से परहेज करें जिन्हें आप वैसे भी अलग करेंगे।

यदि आपके पास इस तरह का एक फंक्शन अप-टू-एन-एन है:

# function version
def fibon(n):
    a = b = 1
    result = []
    for i in xrange(n):
        result.append(a)
        a, b = b, a + b
    return result

आप अधिक आसानी से इस प्रकार फ़ंक्शन लिख सकते हैं:

# generator version
def fibon(n):
    a = b = 1
    for i in xrange(n):
        yield a
        a, b = b, a + b

फ़ंक्शन स्पष्ट है। और यदि आप फ़ंक्शन का उपयोग इस तरह से करते हैं:

for x in fibon(1000000):
    print x,

इस उदाहरण में, यदि जनरेटर संस्करण का उपयोग करते हैं, तो पूरी 1000000 आइटम सूची बिल्कुल भी नहीं बनाई जाएगी, एक समय में केवल एक मूल्य। सूची संस्करण का उपयोग करते समय ऐसा नहीं होगा, जहां पहले एक सूची बनाई जाएगी।


18
और अगर आप एक सूची की ज़रूरत है, तो आप हमेशा कर सकते हैंlist(fibon(5))
endolith

41

PEP 255 में "प्रेरणा" अनुभाग देखें ।

जनरेटर का एक गैर-स्पष्ट उपयोग रुकावटपूर्ण कार्य बना रहा है, जो आपको थ्रेड्स का उपयोग नहीं करते समय अपडेट यूआई या कई काम "एक साथ" (इंटरएलेव्ड, वास्तव में) चलाने की सुविधा देता है।


1
प्रेरणा अनुभाग इस बात में अच्छा है कि इसका एक विशिष्ट उदाहरण है: "जब एक उत्पादक फ़ंक्शन के पास एक कठिन पर्याप्त काम होता है, जिसे उत्पादित मूल्यों के बीच स्थिति बनाए रखने की आवश्यकता होती है, तो अधिकांश प्रोग्रामिंग भाषाएं निर्माता के तर्क में कॉलबैक फ़ंक्शन को जोड़ने से परे कोई सुखद और कुशल समाधान प्रदान करती हैं। सूची ... उदाहरण के लिए, मानक लाइब्रेरी में tokenize.py इस दृष्टिकोण को लेता है "
बेन क्रेसी

38

मुझे यह स्पष्टीकरण मिल गया है जो मेरे संदेह को दूर करता है। क्योंकि इस बात की संभावना है कि जो व्यक्ति नहीं जानता है वह Generatorsभी इसके बारे में नहीं जानता हैyield

वापसी

रिटर्न स्टेटमेंट वह जगह है जहां सभी स्थानीय चर नष्ट हो जाते हैं और परिणामी मूल्य कॉलर को वापस (लौटा) दिया जाता है। उसी फ़ंक्शन को कुछ समय बाद कहा जाना चाहिए, फ़ंक्शन को चर का एक नया नया सेट मिलेगा।

मान जाना

लेकिन क्या होगा अगर एक समारोह से बाहर निकलने पर स्थानीय चर नहीं फेंके जाते? इसका तात्पर्य यह है कि हम resume the functionजहां से छूटे थे, वहां जा सकते हैं । यह वह जगह है जहां अवधारणा generatorsपेश की जाती है और yieldकथन फिर से शुरू होता है जहां functionबाईं ओर।

  def generate_integers(N):
    for i in xrange(N):
    yield i

    In [1]: gen = generate_integers(3)
    In [2]: gen
    <generator object at 0x8117f90>
    In [3]: gen.next()
    0
    In [4]: gen.next()
    1
    In [5]: gen.next()

तो यही अजगर के बीच returnऔर yieldबयानों में अंतर है ।

यील्ड स्टेटमेंट वह है जो फंक्शन को जनरेटर फंक्शन बनाता है।

तो जनरेटर बनाने के लिए एक सरल और शक्तिशाली उपकरण हैं। उन्हें नियमित कार्यों की तरह लिखा जाता है, लेकिन yieldजब भी वे डेटा वापस करना चाहते हैं तो वे कथन का उपयोग करते हैं। हर बार अगला () कहा जाता है, जनरेटर फिर से शुरू होता है जहां इसे छोड़ दिया गया था (यह सभी डेटा मानों को याद करता है और कौन सा कथन अंतिम बार निष्पादित किया गया था)।


33

वास्तविक विश्व उदाहरण

मान लें कि आपके MySQL तालिका में 100 मिलियन डोमेन हैं, और आप प्रत्येक डोमेन के लिए एलेक्सा रैंक अपडेट करना चाहेंगे।

पहली बात आपको डेटाबेस से अपने डोमेन नामों का चयन करना है।

मान लें कि आपका टेबल नाम है domainsऔर कॉलम नाम है domain

यदि आप इसका उपयोग करते हैं तो SELECT domain FROM domainsयह 100 मिलियन पंक्तियों को वापस करने जा रहा है जो बहुत अधिक मेमोरी का उपभोग करने वाला है। तो आपका सर्वर क्रैश हो सकता है।

इसलिए आपने प्रोग्राम को बैचों में चलाने का निर्णय लिया। मान लीजिए कि हमारे बैच का आकार 1000 है।

हमारे पहले बैच में हम पहली 1000 पंक्तियों को क्वेरी करेंगे, प्रत्येक डोमेन के लिए एलेक्सा रैंक की जांच करेंगे और डेटाबेस पंक्ति को अपडेट करेंगे।

हमारे दूसरे बैच में हम अगली 1000 पंक्तियों पर काम करेंगे। हमारे तीसरे बैच में यह 2001 से 3000 तक और इसी तरह रहेगा।

अब हमें एक जनरेटर फ़ंक्शन की आवश्यकता है जो हमारे बैचों को उत्पन्न करता है।

यहाँ हमारे जनरेटर समारोह है:

def ResultGenerator(cursor, batchsize=1000):
    while True:
        results = cursor.fetchmany(batchsize)
        if not results:
            break
        for result in results:
            yield result

जैसा कि आप देख सकते हैं, हमारा कार्य yieldपरिणाम को प्रभावित करता है। यदि आपने returnइसके बजाय कीवर्ड का उपयोग किया है yield, तो यह वापस आने के बाद पूरा कार्य समाप्त हो जाएगा।

return - returns only once
yield - returns multiple times

यदि कोई फंक्शन कीवर्ड का उपयोग करता है yieldतो यह एक जनरेटर है।

अब आप इस तरह से पुनरावृत्ति कर सकते हैं:

db = MySQLdb.connect(host="localhost", user="root", passwd="root", db="domains")
cursor = db.cursor()
cursor.execute("SELECT domain FROM domains")
for result in ResultGenerator(cursor):
    doSomethingWith(result)
db.close()

यह अधिक व्यावहारिक होगा, यदि उपज को पुनरावर्ती / डायनामिक प्रोग्रामिंग के संदर्भ में समझाया जा सकता है!
इगौरव

27

बफरिंग। जब यह बड़ी मात्रा में डेटा लाने के लिए कुशल है, लेकिन इसे छोटे टुकड़ों में संसाधित करें, तो एक जनरेटर मदद कर सकता है:

def bufferedFetch():
  while True:
     buffer = getBigChunkOfData()
     # insert some code to break on 'end of data'
     for i in buffer:    
          yield i

उपरोक्त आपको आसानी से प्रसंस्करण से बफरिंग को अलग करने देता है। उपभोक्ता फ़ंक्शन अब केवल बफरिंग के बारे में चिंता किए बिना एक-एक करके मान प्राप्त कर सकता है।


3
यदि getBigChuckOfData आलसी नहीं है, तो मुझे समझ में नहीं आता है कि यहाँ क्या लाभ है। इस फ़ंक्शन के लिए उपयोग मामला क्या है?
सीन जियोफ्रे पीटज

1
लेकिन बात यह है कि, IIUC , bufferedFetch getBigChunkOfData को कॉल करने के लिए आलसी है। यदि getBigChunkOfData पहले से ही आलसी था, तो बफ़र्डफच बेकार हो जाएगा। बफ़रड फ़ेच () में प्रत्येक कॉल एक बफर तत्व को लौटाएगा, भले ही बिगकंक पहले से ही पढ़ा गया हो। और आपको लौटने के लिए स्पष्ट रूप से अगले तत्व की गिनती रखने की आवश्यकता नहीं है, क्योंकि उपज के यांत्रिकी केवल निहित है।
हमीज़ेल ने इस्तीफा दे दिया

21

मैंने पाया है कि जनरेटर आपके कोड को साफ करने और कोड को एन्कैप्सुलेट और संशोधित करने के लिए एक बहुत ही अनोखा तरीका देने में बहुत सहायक हैं। ऐसी स्थिति में जब आपको अपने आंतरिक प्रसंस्करण के आधार पर मूल्यों को लगातार थूकने के लिए कुछ की आवश्यकता होती है और जब आपके कोड में कहीं से कुछ बुलाया जाना चाहिए (और उदाहरण के लिए केवल एक लूप या ब्लॉक के भीतर नहीं), जनरेटर की सुविधा है उपयोग।

एक सार उदाहरण एक फाइबोनैचि संख्या जनरेटर होगा जो लूप के भीतर नहीं रहता है और जब इसे कहीं से भी कॉल किया जाता है तो हमेशा क्रम में अगला नंबर लौटाएगा:

def fib():
    first = 0
    second = 1
    yield first
    yield second

    while 1:
        next = first + second
        yield next
        first = second
        second = next

fibgen1 = fib()
fibgen2 = fib()

अब आपके पास दो फाइबोनैचि संख्या जनरेटर ऑब्जेक्ट हैं जिन्हें आप अपने कोड में कहीं से भी कॉल कर सकते हैं और वे क्रम में हमेशा बड़े फाइबोनैचि संख्याओं को क्रम में वापस करेंगे:

>>> fibgen1.next(); fibgen1.next(); fibgen1.next(); fibgen1.next()
0
1
1
2
>>> fibgen2.next(); fibgen2.next()
0
1
>>> fibgen1.next(); fibgen1.next()
3
5

जनरेटर के बारे में प्यारी बात यह है कि वे वस्तुओं को बनाने के हुप्स के माध्यम से जाने के बिना राज्य का अतिक्रमण करते हैं। उनके बारे में सोचने का एक तरीका "कार्यों" के रूप में है जो उनकी आंतरिक स्थिति को याद करते हैं।

मुझे पायथन जेनरेटरों से फिबोनाची उदाहरण मिला - वे क्या हैं? और थोड़ी कल्पना के साथ, आप कई अन्य स्थितियों के साथ आ सकते हैं जहां जनरेटर forलूप और अन्य पारंपरिक पुनरावृत्तियों के निर्माण के लिए एक बढ़िया विकल्प बनाते हैं ।


19

सरल स्पष्टीकरण: एक forबयान पर विचार करें

for item in iterable:
   do_stuff()

बहुत समय, सभी वस्तुओं iterableको शुरू से वहाँ रहने की आवश्यकता नहीं है, लेकिन मक्खी पर उत्पन्न किया जा सकता है जैसा कि वे आवश्यक हैं। यह दोनों में बहुत अधिक कुशल हो सकता है

  • अंतरिक्ष (आपको सभी वस्तुओं को एक साथ संग्रहीत करने की आवश्यकता नहीं है) और
  • समय (सभी आइटम आवश्यक होने से पहले पुनरावृत्ति समाप्त हो सकती है)।

अन्य बार, आप समय से पहले सभी वस्तुओं को नहीं जानते हैं। उदाहरण के लिए:

for command in user_input():
   do_stuff_with(command)

आपके पास पहले से सभी उपयोगकर्ता के आदेशों को जानने का कोई तरीका नहीं है, लेकिन आप एक अच्छा लूप का उपयोग कर सकते हैं यदि आपके पास एक जनरेटर है जो आपको आदेश दे रहा है:

def user_input():
    while True:
        wait_for_command()
        cmd = get_command()
        yield cmd

जनरेटर के साथ आप अनंत अनुक्रमों पर भी पुनरावृत्ति कर सकते हैं, जो निश्चित रूप से कंटेनरों पर पुनरावृत्ति करते समय संभव नहीं है।


... और एक अनंत अनुक्रम एक छोटी सूची पर बार-बार साइकिल चलाने से उत्पन्न हो सकता है, अंत तक पहुंचने के बाद शुरुआत में लौटता है। मैं इसका उपयोग रेखांकन में रंग चुनने, या पाठ में व्यस्त थ्रोबर्स या स्पिनरों के उत्पादन के लिए करता हूं।
लेडी पंजकोव

@ ममताप: इसके itertoolलिए एक उपाय है - देखें cycles
मार्टीन्यू

12

मेरे पसंदीदा उपयोग "फिल्टर" और "कम" ऑपरेशन हैं।

मान लीजिए कि हम एक फ़ाइल पढ़ रहे हैं, और केवल वही लाइनें चाहते हैं जो "##" से शुरू होती हैं।

def filter2sharps( aSequence ):
    for l in aSequence:
        if l.startswith("##"):
            yield l

हम एक उचित लूप में जनरेटर फ़ंक्शन का उपयोग कर सकते हैं

source= file( ... )
for line in filter2sharps( source.readlines() ):
    print line
source.close()

कम उदाहरण समान है। मान लीजिए कि हमारे पास एक फ़ाइल है जहाँ हमें <Location>...</Location>लाइनों के ब्लॉक का पता लगाने की आवश्यकता है । [एचटीएमएल टैग नहीं, लेकिन टैग जैसी दिखने वाली लाइनें।]

def reduceLocation( aSequence ):
    keep= False
    block= None
    for line in aSequence:
        if line.startswith("</Location"):
            block.append( line )
            yield block
            block= None
            keep= False
        elif line.startsWith("<Location"):
            block= [ line ]
            keep= True
        elif keep:
            block.append( line )
        else:
            pass
    if block is not None:
        yield block # A partial block, icky

फिर, हम इस जनरेटर का उपयोग लूप के लिए उचित तरीके से कर सकते हैं।

source = file( ... )
for b in reduceLocation( source.readlines() ):
    print b
source.close()

विचार यह है कि एक जनरेटर फ़ंक्शन हमें एक अनुक्रम को फ़िल्टर करने या कम करने की अनुमति देता है, जो एक समय में एक और अनुक्रम एक मूल्य का उत्पादन करता है।


8
fileobj.readlines()जनरेटर का उपयोग करने के उद्देश्य को पराजित करते हुए, पूरी फ़ाइल को स्मृति में एक सूची में पढ़ा जाएगा। चूंकि फ़ाइल ऑब्जेक्ट पहले से ही चलने योग्य हैं, आप for b in your_generator(fileobject):इसके बजाय उपयोग कर सकते हैं । इस तरह आपकी फ़ाइल को एक बार में एक लाइन पढ़ी जाएगी, ताकि पूरी फ़ाइल पढ़ने से बच सके।
nosklo

घटाना बहुत अजीब उपज है एक सूची है, क्यों न केवल प्रत्येक पंक्ति उपज? इसके अलावा फ़िल्टर और कम करने के लिए अपेक्षित व्यवहार के साथ बिलिंस हैं (ipython आदि में मदद देखें), "कम करें" का आपका उपयोग फ़िल्टर के समान है।
जेम्स एंटिल

रीडलाइन पर अच्छा बिंदु ()। मुझे आमतौर पर पता चलता है कि यूनिट परीक्षण के दौरान फाइलें प्रथम श्रेणी के लाइन पुनरावृत्तियों हैं।
S.Lott

दरअसल, "कमी" कई अलग-अलग लाइनों को एक समग्र वस्तु में मिला रही है। ठीक है, यह एक सूची है, लेकिन यह अभी भी स्रोत से ली गई कमी है।
S.Lott

9

एक व्यावहारिक उदाहरण जहां आप एक जनरेटर का उपयोग कर सकते हैं यदि आपके पास किसी प्रकार का आकार है और आप इसके कोनों, किनारों या जो भी हो, उस पर पुनरावृति करना चाहते हैं। अपने स्वयं के प्रोजेक्ट के लिए ( यहाँ स्रोत कोड ) मेरे पास एक आयत थी:

class Rect():

    def __init__(self, x, y, width, height):
        self.l_top  = (x, y)
        self.r_top  = (x+width, y)
        self.r_bot  = (x+width, y+height)
        self.l_bot  = (x, y+height)

    def __iter__(self):
        yield self.l_top
        yield self.r_top
        yield self.r_bot
        yield self.l_bot

अब मैं इसके कोनों पर एक आयत और लूप बना सकता हूँ:

myrect=Rect(50, 50, 100, 100)
for corner in myrect:
    print(corner)

इसके बजाय __iter__आपके पास एक विधि iter_cornersऔर कॉल हो सकती है for corner in myrect.iter_corners()। यह उपयोग करने के लिए सिर्फ और अधिक सुरुचिपूर्ण है __iter__तब से हम सीधे forअभिव्यक्ति में वर्ग उदाहरण नाम का उपयोग कर सकते हैं ।


मैंने जनरेटर के रूप में समान श्रेणी के क्षेत्रों को पारित करने के विचार को
स्वीकार किया

7

मूल रूप से कॉल-बैक फ़ंक्शंस से परहेज जब इनपुट बनाए रखने की स्थिति पर पुनरावृति होती है।

जनरेटर का उपयोग करके क्या किया जा सकता है, इसके अवलोकन के लिए यहां और यहां देखें ।


4

यहाँ पर कुछ अच्छे उत्तर हैं, हालाँकि, मैं पायथन फंक्शनल प्रोग्रामिंग ट्यूटोरियल के बारे में पूरी तरह से पढ़ने की सलाह देता हूँ, जो जनरेटर के कुछ अधिक शक्तिशाली उपयोग-मामलों की व्याख्या करने में मदद करता है।


3

चूंकि जनरेटर की भेजने की विधि का उल्लेख नहीं किया गया है, यहां एक उदाहरण है:

def test():
    for i in xrange(5):
        val = yield
        print(val)

t = test()

# Proceed to 'yield' statement
next(t)

# Send value to yield
t.send(1)
t.send('2')
t.send([3])

यह एक चालू जनरेटर को एक मूल्य भेजने की संभावना दर्शाता है। नीचे दिए गए वीडियो में जनरेटर पर एक और अधिक उन्नत पाठ्यक्रम ( yieldअन्वेषण से, समानांतर प्रसंस्करण के लिए जनरेटर, पुनरावृत्ति से बचने, आदि)

डेविड बेन्ज़ले पाइकॉन 2014 में जनरेटर पर


2

जब हमारा वेब सर्वर प्रॉक्सी की तरह काम कर रहा हो तो मैं जनरेटर का उपयोग करता हूं:

  1. क्लाइंट सर्वर से एक अनुमानित url का अनुरोध करता है
  2. सर्वर लक्ष्य url को लोड करना शुरू करता है
  3. सर्वर क्लाइंट को परिणाम मिलते ही उन्हें वापस करने के लिए देता है

1

सामान के ढेर। किसी भी समय आप वस्तुओं का एक क्रम उत्पन्न करना चाहते हैं, लेकिन उन सभी को एक बार में सूची में 'भौतिक' नहीं करना चाहते हैं। उदाहरण के लिए, आपके पास एक साधारण जनरेटर हो सकता है जो प्रमुख संख्या देता है:

def primes():
    primes_found = set()
    primes_found.add(2)
    yield 2
    for i in itertools.count(1):
        candidate = i * 2 + 1
        if not all(candidate % prime for prime in primes_found):
            primes_found.add(candidate)
            yield candidate

आप बाद के प्राइम के उत्पादों को उत्पन्न करने के लिए इसका उपयोग कर सकते हैं:

def prime_products():
    primeiter = primes()
    prev = primeiter.next()
    for prime in primeiter:
        yield prime * prev
        prev = prime

ये काफी तुच्छ उदाहरण हैं, लेकिन आप देख सकते हैं कि यह बड़े (संभावित अनंत!) डेटासेट के प्रसंस्करण के लिए कैसे उपयोगी हो सकता है, उन्हें अग्रिम में उत्पन्न किए बिना, जो कि अधिक स्पष्ट उपयोगों में से एक है।


यदि कोई नहीं है (primes_found में प्राइम के लिए उम्मीदवार% प्राइम) सभी होना चाहिए (primes_found में प्राइम के लिए उम्मीदवार% प्राइम)
rjmunro

हां, मेरा मतलब था "अगर कोई नहीं (उम्मीदवार% Prime == 0 प्राइम फॉर प्राइम्स_फाउंड में)। आपका थोड़ा नटखट है, हालांकि। :)
निक जॉनसन

मुझे लगता है कि आप (primes_found में प्रधानमंत्री पद के लिए उम्मीदवार% प्रधानमंत्री) नहीं तो सब से 'नहीं' को हटाना भूल गया
Thava

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.