2013-01-19 89 views
35

कोड के इस टुकड़े में, 'फॉर' परिणाम का उपयोग क्यों नहीं किया जाता है 'StopIteration' या 'अप' लूप सभी अपवादों को फँसाने और फिर चुपचाप बाहर निकलने का उपयोग क्यों करता है? किस मामले में, हमारे पास बाहरी 'वापसी' क्यों है ?? या raise StopIteration के कारण: return None है? return None:अगला 'स्टॉपइटरेशन' क्यों बढ़ाता है, लेकिन 'के लिए' सामान्य वापसी करता है?

#!/usr/bin/python3.1 
def countdown(n): 
    print("counting down") 
    while n >= 9: 
     yield n 
     n -= 1 
    return 

for x in countdown(10): 
    print(x) 

c = countdown(10) 
next(c) 
next(c) 
next(c) 

मान लिया जाये कि StopIteration से शुरू हो रहा जा रहा है। जेनरेटरएक्सिट जेनरेट कब होता है?

def countdown(n): 
    print("Counting down from %d" % n) 
    try: 
     while n > 0: 
      yield n 
      n = n - 1 
    except GeneratorExit: 
     print("Only made it to %d" % n) 

तो मैं स्वयं एक कार्य करें:

c = countdown(10) 
c.close() #generates GeneratorExit?? 

जो मामले में कारण है कि मैं एक ट्रैस नहीं दिखाई देता?

उत्तर

44

for लूप StopIteration स्पष्ट रूप से सुनता है।

for कथन का उद्देश्य एक पुनरावर्तक द्वारा प्रदान किए गए अनुक्रम पर लूप करना है और अपवाद का उपयोग यह संकेत करने के लिए किया जाता है कि इटरेटर अब किया गया है; for ऑब्जेक्ट द्वारा उठाए गए ऑब्जेक्ट द्वारा उठाए गए अन्य अपवादों को नहीं पकड़ता है, बस एक ही।

ऐसा इसलिए है क्योंकि StopIteration सामान्य, अपेक्षित सिग्नल है जो यह कहने के लिए है कि उत्पादित होने के लिए और कुछ भी नहीं है।

एक जेनरेटर फ़ंक्शन एक विशेष प्रकार का इटरेटर है; जब यह कार्य पूरा हो जाता है तो यह वास्तव में StopIteration उठाता है (यानी जब यह लौटाता है, तो हाँ, return NoneStopIteration बढ़ाता है)। यह इटरेटर की आवश्यकता है; वे StopIteration बढ़ाए जाने पर; वास्तव में, एक बार एक StopIteration कर दी गई है, उनमें से एक और तत्व प्राप्त करने का प्रयास (next() के माध्यम से, या .next() (py 2) या .__next__() (py 3) पुनरावर्तक पर विधि बुला) हमेशा फिर से StopIteration उठाना चाहिए।

GeneratorExitअन्य दिशा में संवाद करने का अपवाद है। आप स्पष्ट रूप से yield अभिव्यक्ति वाले जनरेटर को बंद कर रहे हैं, और जिस तरह से पाइथन संवाद करता है कि जनरेटर को बंद करना उस कार्य के अंदर GeneratorExit उठाकर है। आप countdown के अंदर उस अपवाद को स्पष्ट रूप से पकड़ते हैं, इसका उद्देश्य जनरेटर को बंद होने पर आवश्यक संसाधनों को साफ करने देना है।

GeneratorExit कॉलर को प्रचारित नहीं किया गया है; generator.close() documentation देखें।

+5

यह भी ध्यान दें, क्योंकि इटेटरेटर का मूल्यांकन करते समय केवल अपवाद को पकड़ लिया जाएगा। अगर यह लूप के शरीर के भीतर उठाया जाता है तो यह इसे पकड़ नहीं पाएगा। –

+1

@ जोनासविएलिकी: उस व्याख्या को हटाने के लिए वाक्य को थोड़ा बढ़ाया। :-) –