एक सूची समझ में अपवादों को कैसे संभालें?


120

मुझे पायथन में कुछ सूची समझ है जिसमें प्रत्येक पुनरावृत्ति एक अपवाद को फेंक सकती है।

उदाहरण के लिए , अगर मेरे पास:

eggs = (1,3,0,3,2)

[1/egg for egg in eggs]

मुझे ZeroDivisionError3 तत्व में एक अपवाद मिलेगा ।

मैं इस अपवाद को कैसे संभाल सकता हूं और सूची की समझ का निष्पादन जारी रख सकता हूं?

जिस तरह से मैं सोच सकता हूँ कि एक सहायक समारोह का उपयोग करना है:

def spam(egg):
    try:
        return 1/egg
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

लेकिन यह मुझे थोड़ा बोझिल लगता है।

क्या पायथन में ऐसा करने का एक बेहतर तरीका है?

नोट: यह एक सरल उदाहरण है ( ऊपर " उदाहरण के लिए देखें" ) जो मैंने विवादित था क्योंकि मेरे वास्तविक उदाहरण के लिए कुछ संदर्भ की आवश्यकता है। मैं शून्य त्रुटियों से विभाजित होने से बचने में दिलचस्पी नहीं रखता लेकिन सूची समझ में अपवादों को संभालने में।


4
अपवादों को संभालने के लिए एक अभिव्यक्ति जोड़ने के लिए एक पीईपी 463 है। आपके उदाहरण में यह होगा [1/egg except ZeroDivisionError: None for egg in (1,3,0,3,2)]। लेकिन यह अभी भी ड्राफ्ट मोड में है। मेरी आंत की भावना यह है कि यह स्वीकार नहीं किया जाएगा। Imho अभिव्यक्तियाँ बहुत गन्दा हो सकता है (कई अपवादों की जाँच, अधिक जटिल संयोजन (कई तार्किक ऑपरेटर, जटिल समझ, आदि)
cfi

1
ध्यान दें कि इस विशिष्ट उदाहरण के लिए, आप ndarrayउपयुक्त सेटिंग्स के साथ एक अंक का उपयोग कर सकते हैं np.seterr। इसके परिणामस्वरूप होगा 1/0 = nan। लेकिन मुझे लगता है कि यह उन अन्य स्थितियों के लिए सामान्य नहीं है जहां यह आवश्यकता होती है।
गेरिट जूल

जवाबों:


96

पायथन में कोई अंतर्निहित अभिव्यक्ति नहीं है जो आपको एक अपवाद को अनदेखा करने देता है (या अपवादों के मामले में वैकल्पिक मूल्यों और ग) लौटाता है, इसलिए यह असंभव है, शाब्दिक रूप से बोलना, "एक सूची समझ में अपवादों को संभालना" क्योंकि एक सूची समझ की अभिव्यक्ति है। अन्य अभिव्यक्ति वाले, अधिक कुछ नहीं (यानी, कोई बयान नहीं , और केवल बयान अपवाद को पकड़ / अनदेखा / संभाल सकते हैं)।

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

इस सवाल का सही जवाब "एक सूची समझ में अपवादों को कैसे संभालना है" ये सभी इस सत्य का सभी व्यक्त हिस्सा हैं: 1) शाब्दिक रूप से, यानी लेक्सिकली खुद समझ नहीं सकते; 2) व्यावहारिक रूप से, आप नौकरी को किसी फ़ंक्शन में सौंपते हैं या जब यह संभव होता है तो त्रुटि प्रवण मानों की जांच करते हैं। आपका दोहराया गया दावा है कि यह उत्तर नहीं है और इस तरह निराधार है।


14
समझा। तो एक पूर्ण उत्तर यह होगा कि मुझे या तो होना चाहिए: 1. एक फ़ंक्शन का उपयोग करें। सूची समझ का उपयोग न करें 3. इसे संभालने के बजाय अपवाद को रोकने का प्रयास करें।
नाथन फ़ेलमैन

9
मैं "सूची बोध में अपवादों को कैसे संभालना है" के जवाब के एक भाग के रूप में "सूची संकलन का उपयोग नहीं करना" नहीं देखता, लेकिन मुझे लगता है कि आप इसे यथोचित रूप से " एलसीई के रूप में नियंत्रण रेखा में देख सकते हैं, यह संभव है।" संभाल अपवाद ", जो वास्तव में शाब्दिक उत्तर का पहला हिस्सा है।
एलेक्स मार्टेली

क्या आप एक जनरेटर अभिव्यक्ति या जनरेटर समझ में त्रुटि पकड़ सकते हैं?

1
@AlexMartelli, क्या सिवाय एक खंड के कि भविष्य के अजगर संस्करणों में काम करना मुश्किल होगा? [x[1] for x in list except IndexError pass]। क्या दुभाषिया कोशिश करने के लिए एक अस्थायी कार्य नहीं कर सकता है x[1]?
अलंकलवित्ति

@ नथन, 1,2,3 ऊपर कार्यात्मक डेटा प्रवाह में जबरदस्त सिरदर्द में बदल जाता है, जहां 1. लैंबडास के माध्यम से आम तौर पर इनलाइन कार्यों को करना चाहता है; 2. वैकल्पिक लूप के लिए बहुत सारे नेस्टेड का उपयोग कर रहा है जो कार्यात्मक प्रतिमान का उल्लंघन करता है और त्रुटि प्रवण कोड का नेतृत्व करता है; 3. अक्सर त्रुटियों को तदर्थ और अव्यक्त जटिल डेटासेट होते हैं, जो डेटा के लिए लैटिन शब्द के रूप में दिए गए हैं, इसलिए आसानी से रोका नहीं जा सकता है।
अलंकलवित्ति

118

मुझे एहसास है कि यह प्रश्न काफी पुराना है, लेकिन आप इस तरह की चीज़ को आसान बनाने के लिए एक सामान्य फ़ंक्शन भी बना सकते हैं:

def catch(func, handle=lambda e : e, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        return handle(e)

फिर, आपकी समझ में:

eggs = (1,3,0,3,2)
[catch(lambda : 1/egg) for egg in eggs]
[1, 0, ('integer division or modulo by zero'), 0, 0]

आप निश्चित रूप से डिफॉल्ट हैंडल फंक्शन कर सकते हैं, जो भी आप चाहते हैं (कहते हैं कि आप डिफ़ॉल्ट रूप से 'कोई नहीं' लौटाएंगे)।

आशा है कि यह आपको या भविष्य के किसी भी दर्शक को इस सवाल में मदद करेगा!

नोट: पायथन 3 में, मैं केवल 'हैंडल' तर्क कीवर्ड बनाऊंगा, और इसे तर्क सूची के अंत में रखूंगा। यह वास्तव में गुजरती तर्कों और इस तरह के माध्यम से पकड़ और अधिक प्राकृतिक होगा।


2
अत्यंत उपयोगी, धन्यवाद। जबकि मैं सैद्धांतिक टिप्पणियों से सहमत हूं, यह एक समस्या को हल करने के लिए एक व्यावहारिक दृष्टिकोण दिखाता है जो मैंने बार-बार किया है।
पॉल

2
ग्रेटे उत्तर। एक मॉड मैं सुझाऊंगा argsऔर kwargsसाथ ही साथ संभालना होगा। इस तरह आप eggहार्डकोड के बजाय कह सकते हैं 0, या आप जैसा कर रहे हैं वैसा एक अपवाद।
मैड फिजिसिस्ट

3
आप अपवाद प्रकार को एक वैकल्पिक तर्क के रूप में भी देख सकते हैं (अपवाद प्रकार को समरूप किया जा सकता है?), ताकि सभी अपवादों को अनदेखा करने के बजाय अप्रत्याशित अपवादों को ऊपर की ओर फेंका जाए।
00prometheus

3
@ ब्रायन, क्या आप "अजगर 3 में कोड प्रदान कर सकते हैं, मैं केवल 'हैंडल' तर्क कीवर्ड बनाऊंगा, और इसे तर्क सूची के अंत में रखूंगा।" के handleबाद रखने की कोशिश की **kwargऔर एक मिल गया SyntaxError। क्या आप के रूप में हस्तक्षेप करने का मतलब है kwargs.get('handle',e)?
अलंकालविटि

21

आप उपयोग कर सकते हैं

[1/egg for egg in eggs if egg != 0]

यह केवल उन तत्वों को छोड़ देगा जो शून्य हैं।


28
यह इस सवाल का जवाब नहीं देता है कि सूची समझ में अपवादों को कैसे संभालना है।
नाथन फेलमैन

8
उम, हाँ, यह करता है। यह अपवादों को संभालने की आवश्यकता को कम करता है। हां, यह हर समय सही समाधान नहीं है, लेकिन यह एक आम है।
पीटर

3
मै समझता हुँ। मैं टिप्पणी वापस लेता हूं (हालांकि मैं इसे नहीं हटाऊंगा क्योंकि उत्तर पर संक्षिप्त 'चर्चा' में सुधार होता है)।
नाथन फ़ेलमैन

11

कोई बेहतर तरीका नहीं है। कई मामलों में आप पीटर की तरह परहेज का उपयोग कर सकते हैं

आपका दूसरा विकल्प समझ का उपयोग नहीं करना है

eggs = (1,3,0,3,2)

result=[]
for egg in eggs:
    try:
        result.append(egg/0)
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

यह तय करने के लिए कि आप अधिक बोझिल हैं या नहीं


1
मैं यहाँ कैसे समझ का उपयोग करूँगा?
नाथन फेलमैन

@ नथन: आप नहीं करेंगे। gnibbler कहते हैं: नहीं वहाँ एक बेहतर तरीका नहीं है
साइलेंटगॉस्ट

क्षमा करें ... मुझे उसके उत्तर में याद नहीं ':-)
नाथन फ़ेलमैन

4

मुझे लगता है कि एक हेल्पर फंक्शन, जैसा कि शुरुआती सवाल और ब्रायन हेड से भी पूछा गया है, अच्छा है और बिल्कुल भी बोझिल नहीं है। जादू कोड की एक पंक्ति जो सभी काम करती है वह हमेशा संभव नहीं होती है इसलिए हेल्पर फ़ंक्शन एक सही समाधान है यदि कोई forछोरों से बचना चाहता है । हालाँकि मैं इसे इसे संशोधित करूंगा:

# A modified version of the helper function by the Question starter 
def spam(egg):
    try:
        return 1/egg, None
    except ZeroDivisionError as err:
        # handle division by zero error        
        return None, err

आउटपुट यह होगा [(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]। इस उत्तर के साथ आप किसी भी तरह से जारी रखना चाहते हैं।


अच्छा लगा। यह Eitherकुछ कार्यात्मक प्रोग्रामिंग भाषाओं (जैसे स्काला) के प्रकार के समान दिखता है , जहां Eitherएक प्रकार या किसी अन्य का मान हो सकता है, लेकिन दोनों। अंतर केवल इतना है कि उन भाषाओं में त्रुटि को बाईं ओर और मूल्य को दाईं ओर रखना मुहावरेदार है। यहां अधिक जानकारी वाला एक लेख है
एलेक्स पामर

3

मुझे इसका कोई जवाब नहीं मिला। लेकिन यह उदाहरण एक अपवाद को रोकने का एक तरीका होगा जिसे ज्ञात असफल मामलों के लिए उठाया जा सकता है।

eggs = (1,3,0,3,2)
[1/egg if egg > 0 else None for egg in eggs]


Output: [1, 0, None, 0, 0]

क्या यह उत्तर जैसा नहीं है? stackoverflow.com/a/1528244/1084
नाथन फेलमैन

सूक्ष्म अंतर है। फ़िल्टरिंग इनपुट सूची के बजाय आउटपुट पर लागू किया जाता है। जैसा कि आप पोस्ट किए गए उदाहरण में देख सकते हैं, मैंने उस मामले के लिए "कोई नहीं" निरूपित किया है जो अपवाद हो सकता है।
15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.