2011-01-19 11 views
110

मेरे पास एक जनरेटर फ़ंक्शन निम्न जैसा है:जेनरेटर (पायथन में) से केवल एक आइटम कैसे चुनें?

def myfunct(): 
    ... 
    yield result 

इस फ़ंक्शन को कॉल करने का सामान्य तरीका यह होगा:

for r in myfunct(): 
    dostuff(r) 

मेरा प्रश्न, जनरेटर से केवल एक तत्व प्राप्त करने का कोई तरीका है मुझे पसंद है? उदाहरण के लिए, मैं कुछ ऐसा करना चाहता हूं:

while True: 
    ... 
    if something: 
     my_element = pick_just_one_element(myfunct()) 
     dostuff(my_element) 
    ... 

उत्तर

161

, एक जनरेटर का उपयोग

g = myfunct() 

हर आप एक आइटम चाहते हैं बनाएं का उपयोग

g.next() 

या

next(g) 

यदि जेनरेटर निकलता है, यह StopIteration बढ़ाएगा। आप या तो यदि आवश्यक हो तो इस अपवाद को पकड़ने, या next() को default तर्क का उपयोग कर सकते हैं:

next(g, default_value) 
+3

नोट, जब आप जी में अंतिम आइटम प्रदान किए जाने के बाद g.next() का उपयोग करने का प्रयास करते हैं तो यह केवल स्टॉपइटरेशन बढ़ाएगा। 'StopIteration' अपवाद से बचने के लिए – Wilduck

+15

'अगला (जेन, डिफ़ॉल्ट)' का भी उपयोग किया जा सकता है। उदाहरण के लिए तारों के जनरेटर के लिए 'अगला (जी, कोई नहीं)' या तो पुनरावृत्ति समाप्त होने के बाद स्ट्रिंग या कोई भी उपज नहीं करेगा। पाइथन 3000 में – Attila

+4

, अगला() __next __() –

-1

मेरा मानना ​​है कि एक ही रास्ता पुनरावर्तक से एक सूची प्राप्त करने तो तत्व आपको उस सूची में चाहते है।

l = list(myfunct()) 
l[4] 
+0

स्वेन का जवाब शायद बेहतर है, लेकिन मैं इसे यहां छोड़ दूंगा क्योंकि यह आपकी आवश्यकताओं के साथ अधिक इनलाइन है। – keegan3d

+22

यह सुनिश्चित करने से पहले कि आपके पास एक सीमित जनरेटर है, सुनिश्चित करें। – Seth

+5

क्षमा करें, इसमें जटिलता की लंबाई जटिलता है, जबकि समस्या स्पष्ट रूप से ओ (1) है। –

2

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

0
generator = myfunct() 
while True: 
    my_element = generator.next() 

अपने उदाहरण के अनुसार अपवाद पिछले तत्व

+0

पायथन 3 के लिए मान्य नहीं है, उत्कृष्ट [kxr द्वारा जवाब] देखें (http://stackoverflow.com/a/35370041/260122)। – clacke

12

लिया जाता है एक for बयान में एक जनरेटर उपयोग break का सिर्फ एक तत्व उठा लिए के बाद फेंक दिया को पकड़ने के लिए सुनिश्चित करें, या list(itertools.islice(gen, 1))

(litterally) आप कर सकते हैं की तरह:

while True: 
    ... 
    if something: 
     for my_element in myfunct(): 
      dostuff(my_element) 
      break 
     else: 
      do_generator_empty() 

यदि आप चाहते हैं "जूस मिल

gen = myfunct() 
while True: 
    ... 
    if something: 
     for my_element in gen: 
      dostuff(my_element) 
      break 
     else: 
      do_generator_empty() 

इस तरह generator.next() की स्पष्ट इस्तेमाल किया जा सकता: टी [एक बार उत्पन्न] जनरेटर जब भी मैं तरह "से एक तत्व तो (मैं मूल इरादा thats 50%, और सबसे आम इरादा लगता है) से बचाया गया है, और अंत में इनपुट हैंडलिंग की आवश्यकता नहीं है (क्रिप्टिक) StopIteration अपवाद हैंडलिंग या अतिरिक्त डिफ़ॉल्ट मान तुलना।

else:for कथन अनुभाग केवल तभी जरूरी है जब आप अंत-जेनरेटर के मामले में कुछ विशेष करना चाहते हैं।next()/.next() पर

नोट:

python3 में .next() विधि अच्छे कारण के लिए .__next__() को नाम दिया गया था: अपने विचार निम्न स्तर (पीईपी 3114)। पायथन 2.6 से पहले बिल्टिन फ़ंक्शन next() मौजूद नहीं था। और next() को operator मॉड्यूल (जो बुद्धिमान होगा) पर जाने के लिए भी चर्चा की गई थी, क्योंकि इसकी नाम की दुर्लभ आवश्यकता और संदिग्ध मुद्रास्फीति की वजह से।

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

नीचे पंक्ति: अगले() का उपयोग करना बहुत दुर्लभ होना चाहिए - operator मॉड्यूल के कार्यों का उपयोग करना। for x in iterator, islice, list(iterator) का उपयोग करना और एक इटरेटर को सहजता से स्वीकार करने वाले अन्य कार्य अनुप्रयोग स्तर पर इटरेटर का उपयोग करने का प्राकृतिक तरीका है - और हमेशा संभव है। next() निम्न स्तर, एक अतिरिक्त अवधारणा, अनौपचारिक है - क्योंकि इस धागे के सवाल से पता चलता है। उदाहरण के लिए break का उपयोग for में पारंपरिक है।

+0

यह सूची परिणाम के पहले तत्व को प्राप्त करने के लिए बहुत अधिक काम है। अक्सर पर्याप्त मुझे आलसी होने की आवश्यकता नहीं है लेकिन py3 में कोई विकल्प नहीं है। क्या 'mySeq.head' जैसा कुछ नहीं है? – javadba

संबंधित मुद्दे