क्या पायथन में ट्राई-एग्ज़ाइट्मेंट का उपयोग करना अच्छा है?


439

पायथन में समय-समय पर, मैं ब्लॉक देखता हूं:

try:
   try_this(whatever)
except SomeException as exception:
   #Handle exception
else:
   return something

प्रयास-अपवाद के कारण-अस्तित्व में और क्या है?

मुझे उस तरह की प्रोग्रामिंग पसंद नहीं है, क्योंकि यह प्रवाह नियंत्रण करने के लिए अपवादों का उपयोग कर रहा है। हालाँकि, अगर यह भाषा में शामिल है, तो इसका एक अच्छा कारण होना चाहिए, है न?

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

आम तौर पर मैं अपवादों को संभालता हूं:

something = some_default_value
try:
    something = try_this(whatever)
except SomeException as exception:
    #Handle exception
finally:
    return something

या अगर मैं वास्तव में कुछ भी वापस नहीं करना चाहता अगर कोई अपवाद होता है, तो:

try:
    something = try_this(whatever)
    return something
except SomeException as exception:
    #Handle exception

जवाबों:


666

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

पायथन दुनिया में, प्रवाह नियंत्रण के अपवादों का उपयोग करना सामान्य और सामान्य है।

यहां तक ​​कि पायथन कोर डेवलपर्स प्रवाह-नियंत्रण के लिए अपवादों का उपयोग करते हैं और उस शैली को भाषा में भारी रूप से बेक किया जाता है (यानी इटरेटर प्रोटोकॉल स्टॉपआईटरेशन का उपयोग सिग्नल लूप टर्मिनेशन के लिए करता है )।

इसके अलावा, कोशिश-अपवाद-शैली का उपयोग "लुक-पहले-आप-लीप" निर्माणों में निहित कुछ दौड़-स्थितियों को रोकने के लिए किया जाता है । उदाहरण के लिए, os.path.exists का परीक्षण करने से जानकारी मिलती है कि यह आपके द्वारा उपयोग किए जाने के समय से पुराना हो सकता है। इसी तरह, Queue.full ऐसी जानकारी देता है जो बासी हो सकती है। कोशिश को छोड़कर-किसी और शैली इन मामलों में और अधिक विश्वसनीय कोड का उत्पादन करेगा।

"यह मेरी समझ है कि अपवाद त्रुटियां नहीं हैं, उनका उपयोग केवल असाधारण स्थितियों के लिए किया जाना चाहिए"

कुछ अन्य भाषाओं में, यह नियम उनके पुस्तकालयों में प्रतिबिंबित उनके सांस्कृतिक मानदंडों को दर्शाता है। "नियम" उन भाषाओं के प्रदर्शन के विचारों पर भी आधारित है।

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

दूसरे शब्दों में, आपकी समझ यह है कि "अपवाद असाधारण के लिए हैं" एक नियम है जो कुछ अन्य भाषाओं में समझ में आता है, लेकिन पायथन के लिए नहीं।

"हालांकि, अगर यह भाषा में ही शामिल है, तो इसके लिए एक अच्छा कारण होना चाहिए, है न?"

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

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

यहां अपवादों की अपरिहार्यता पर एक अच्छा ब्लॉग पोस्ट है

इसके अलावा, इस ढेर अतिप्रवाह उत्तर को देखें: क्या अपवाद वास्तव में असाधारण त्रुटियों के लिए हैं?

"कोशिश-अपवाद के अलावा मौजूद होने का क्या कारण है?"

अन्य-खंड अपने आप में दिलचस्प है। यह तब चलता है जब कोई अपवाद नहीं होता है, लेकिन अंत में क्लॉज से पहले। यही इसका प्राथमिक उद्देश्य है।

अन्य-खंड के बिना, अंतिमकरण से पहले अतिरिक्त कोड चलाने का एकमात्र विकल्प कोड को कोशिश-खंड में जोड़ने का अनाड़ी अभ्यास होगा। यह अनाड़ी है क्योंकि यह कोड में अपवादों को उठाने का जोखिम रखता है जो कि प्रयास-ब्लॉक द्वारा संरक्षित होने का इरादा नहीं था।

अंतिम रूप से पहले अतिरिक्त असुरक्षित कोड चलाने का उपयोग-मामला बहुत बार उत्पन्न नहीं होता है। इसलिए, प्रकाशित कोड में कई उदाहरण देखने की उम्मीद न करें। यह कुछ हद तक दुर्लभ है।

अन्य-क्लॉज के लिए एक और उपयोग-मामला उन कार्यों को करने के लिए होता है जो तब होते हैं जब कोई अपवाद नहीं होता है और जब अपवादों को नियंत्रित नहीं किया जाता है तो ऐसा नहीं होता है। उदाहरण के लिए:

recip = float('Inf')
try:
    recip = 1 / f(x)
except ZeroDivisionError:
    logging.info('Infinite result')
else:
    logging.info('Finite result')

एक और उदाहरण एकतरफा धावक में होता है:

try:
    tests_run += 1
    run_testcase(case)
except Exception:
    tests_failed += 1
    logging.exception('Failing test case: %r', case)
    print('F', end='')
else:
    logging.info('Successful test case: %r', case)
    print('.', end='')

अंत में, ट्राइ-ब्लॉक में एक और क्लॉज का सबसे आम उपयोग सौंदर्यीकरण के एक बिट के लिए है (असाधारण परिणामों और गैर-असाधारण परिणामों को एक ही स्तर पर इंडेंट करने के लिए संरेखित करना)। यह उपयोग हमेशा वैकल्पिक है और सख्ती से आवश्यक नहीं है।


28
"यह अनाड़ी है क्योंकि यह कोड में अपवादों को उठाने का जोखिम रखता है जो कि प्रयास-ब्लॉक द्वारा संरक्षित होने का इरादा नहीं था।" यह यहां सबसे महत्वपूर्ण शिक्षा है
फेलिक्स डॉमबेक

2
जवाब के लिए धन्यवाद। प्रयास-अपवाद-उपयोग के उदाहरणों की तलाश करने वाले पाठकों के लिए, शिल्ट की प्रतिलिपि विधि github.com/python/cpython/blob/master/Lib/shutil.py#L244
sururoori

2
मुद्दा यह है कि दूसरे खंड को केवल तभी निष्पादित किया जाता है जब प्रयास खंड सफल होता है।
जोनाथन

172

प्रयास-अपवाद के कारण-अस्तित्व में और क्या है?

एक tryब्लॉक आपको एक अपेक्षित त्रुटि को संभालने की अनुमति देता है। exceptब्लॉक केवल अपवाद आप को संभालने के लिए तैयार कर रहे हैं पकड़ने चाहिए। यदि आप एक अप्रत्याशित त्रुटि को संभालते हैं, तो आपका कोड गलत काम कर सकता है और बग छिपा सकता है।

elseयदि कोई त्रुटि नहीं थी, तो एक खंड निष्पादित करेगा, और tryब्लॉक में उस कोड को निष्पादित नहीं करने से , आप एक अप्रत्याशित त्रुटि को पकड़ने से बचते हैं। फिर से, एक अप्रत्याशित त्रुटि को पकड़ने से कीड़े छिप सकते हैं।

उदाहरण

उदाहरण के लिए:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
else:
    return something

"प्रयास को छोड़कर" सूट में दो वैकल्पिक खंड हैं, elseऔर finally। तो यह वास्तव में है try-except-else-finally

elseकेवल तभी मूल्यांकन करेगा जब tryब्लॉक से कोई अपवाद नहीं है । यह हमें नीचे दिए गए अधिक जटिल कोड को सरल बनाने की अनुमति देता है:

no_error = None
try:
    try_this(whatever)
    no_error = True
except SomeException as the_exception:
    handle(the_exception)
if no_error:
    return something

इसलिए यदि हम elseविकल्प की तुलना करते हैं (जो बग पैदा कर सकते हैं) तो हम देखते हैं कि यह कोड की रेखाओं को कम कर देता है और हमारे पास अधिक पठनीय, रख-रखाव, और कम बग्गी कोड-बेस हो सकता है।

finally

finally किसी भी मामले को निष्पादित नहीं करेगा, भले ही रिटर्न स्टेटमेंट के साथ एक और लाइन का मूल्यांकन किया जा रहा हो।

छद्म कोड के साथ टूट गया

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

उदाहरण के लिए:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle_SomeException(the_exception)
    # Handle a instance of SomeException or a subclass of it.
except Exception as the_exception:
    generic_handle(the_exception)
    # Handle any other exception that inherits from Exception
    # - doesn't include GeneratorExit, KeyboardInterrupt, SystemExit
    # Avoid bare `except:`
else: # there was no exception whatsoever
    return something()
    # if no exception, the "something()" gets evaluated,
    # but the return will not be executed due to the return in the
    # finally block below.
finally:
    # this block will execute no matter what, even if no exception,
    # after "something" is eval'd but before that value is returned
    # but even if there is an exception.
    # a return here will hijack the return functionality. e.g.:
    return True # hijacks the return in the else clause above

यह सच है कि हम इसके बजाय ब्लॉक में कोड को कोड में शामिल कर सकते हैं , जहां यह अपवाद नहीं होता है, लेकिन क्या होगा यदि वह कोड खुद को पकड़ रहा है जिस तरह के अपवाद को उठाता है? ब्लॉक में छोड़ने से वह बग छिप जाएगा।elsetrytry

हम tryब्लॉक में कोड की लाइनों को कम करना चाहते हैं अपवादों से बचने के लिए हम इस सिद्धांत के तहत उम्मीद नहीं करते थे कि यदि हमारा कोड विफल रहता है, तो हम चाहते हैं कि यह जोर से विफल हो। यह एक सर्वोत्तम अभ्यास है

यह मेरी समझ है कि अपवाद त्रुटियां नहीं हैं

पायथन में, अधिकांश अपवाद त्रुटियां हैं।

हम pydoc का उपयोग करके अपवाद पदानुक्रम देख सकते हैं। उदाहरण के लिए, पायथन 2 में:

$ python -m pydoc exceptions

या पायथन 3:

$ python -m pydoc builtins

हमें पदानुक्रम देंगे। हम देख सकते हैं कि अधिकांश प्रकार की Exceptionत्रुटियां हैं, हालांकि अजगर forछोरों ( StopIteration) को समाप्त करने जैसी चीजों के लिए उनमें से कुछ का उपयोग करता है । यह पायथन 3 का पदानुक्रम है:

BaseException
    Exception
        ArithmeticError
            FloatingPointError
            OverflowError
            ZeroDivisionError
        AssertionError
        AttributeError
        BufferError
        EOFError
        ImportError
            ModuleNotFoundError
        LookupError
            IndexError
            KeyError
        MemoryError
        NameError
            UnboundLocalError
        OSError
            BlockingIOError
            ChildProcessError
            ConnectionError
                BrokenPipeError
                ConnectionAbortedError
                ConnectionRefusedError
                ConnectionResetError
            FileExistsError
            FileNotFoundError
            InterruptedError
            IsADirectoryError
            NotADirectoryError
            PermissionError
            ProcessLookupError
            TimeoutError
        ReferenceError
        RuntimeError
            NotImplementedError
            RecursionError
        StopAsyncIteration
        StopIteration
        SyntaxError
            IndentationError
                TabError
        SystemError
        TypeError
        ValueError
            UnicodeError
                UnicodeDecodeError
                UnicodeEncodeError
                UnicodeTranslateError
        Warning
            BytesWarning
            DeprecationWarning
            FutureWarning
            ImportWarning
            PendingDeprecationWarning
            ResourceWarning
            RuntimeWarning
            SyntaxWarning
            UnicodeWarning
            UserWarning
    GeneratorExit
    KeyboardInterrupt
    SystemExit

एक टिप्पणीकार ने पूछा:

मान लें कि आपके पास एक ऐसा तरीका है जो बाहरी API को पिंग करता है और आप API रैपर के बाहर एक कक्षा में अपवाद को संभालना चाहते हैं, क्या आप केवल अपवाद खंड के तहत विधि से e को वापस लेते हैं जहाँ e अपवाद वस्तु है?

नहीं, आप अपवाद को वापस नहीं करते हैं, बस स्टैच्रेस raiseको संरक्षित करने के लिए इसे एक नंगे के साथ रेयर करें।

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    raise

या, पायथन 3 में, आप एक नया अपवाद जुटा सकते हैं और अपवाद के आधार पर बैकट्रेस को संरक्षित कर सकते हैं:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    raise DifferentException from the_exception

मैं यहां अपने उत्तर में विस्तार से बताता हूं


upvoted! आप आमतौर पर हैंडल भाग के अंदर क्या करते हैं? मान लीजिए कि आपके पास एक विधि है जो बाहरी एपीआई को पिंग करती है और आप एपीआई आवरण के बाहर एक वर्ग पर अपवाद को संभालना चाहते हैं, क्या आप केवल अपवाद खंड के तहत विधि से ई वापस करते हैं जहां ई अपवाद वस्तु है?
पाइरेटऐप

1
@PirateApp आपको धन्यवाद! नहीं, इसे वापस न करें, आपको शायद एक नंगे के साथ फिर से जागना चाहिए raiseया अपवाद का पीछा करना चाहिए - लेकिन यह विषय पर अधिक है और यहां कवर किया गया है: stackoverflow.com/q/2052390/541136 - मैं शायद इन टिप्पणियों को हटा दूँगा देखा आपने उन्हें देखा है।
हारून हॉल

विवरण के लिए बहुत बहुत धन्यवाद! अब पोस्ट के माध्यम से जा रहा है
PirateApp

36

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

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

कल्पना करें कि आपके पास एक ऐसी स्थिति है जहाँ आप कुछ उपयोगकर्ता इनपुट लेते हैं जिसे संसाधित करने की आवश्यकता होती है, लेकिन एक डिफ़ॉल्ट है जो पहले से ही संसाधित है। try: ... except: ... else: ...संरचना बहुत पठनीय कोड के लिए बनाता है:

try:
   raw_value = int(input())
except ValueError:
   value = some_processed_value
else: # no error occured
   value = process_value(raw_value)

इसकी तुलना अन्य भाषाओं में कैसे हो सकती है:

raw_value = input()
if valid_number(raw_value):
    value = process_value(int(raw_value))
else:
    value = some_processed_value

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

उदाहरण स्वाभाविक रूप से थोड़ा वंचित है, लेकिन यह दिखाता है कि इस संरचना के मामले हैं।


15

क्या अजगर में ट्राई-एग्जिट-और का उपयोग करना अच्छा है?

इसका उत्तर यह है कि यह संदर्भ पर निर्भर है। अगर तुम यह करते हो:

d = dict()
try:
    item = d['item']
except KeyError:
    item = 'default'

यह दर्शाता है कि आप पायथन को बहुत अच्छी तरह से नहीं जानते हैं। इस कार्यक्षमता dict.getविधि में समझाया गया है :

item = d.get('item', 'default')

try/ exceptब्लॉक लेखन क्या कुशलता से एक परमाणु विधि के साथ एक पंक्ति में क्रियान्वित किया जा सकता है की एक बहुत अधिक नेत्रहीन भरा हुआ और वर्बोज़ तरीका है। ऐसे अन्य मामले हैं जहां यह सच है।

हालांकि, इसका मतलब यह नहीं है कि हमें सभी अपवाद हैंडलिंग से बचना चाहिए। कुछ मामलों में यह दौड़ की स्थिति से बचने के लिए पसंद किया जाता है। यदि कोई फ़ाइल मौजूद है, तो उसे चेक करने का प्रयास न करें, और उचित IOError को पकड़ें। सरलता और पठनीयता की खातिर, इस या कारक को एप्रोपोस के रूप में समझाया जाना चाहिए।

पायथन के ज़ेन को पढ़ें , यह समझते हुए कि ऐसे सिद्धांत हैं जो तनाव में हैं, और हठधर्मिता से सावधान रहें जो इसमें किसी भी एक बयान पर बहुत अधिक निर्भर करता है।


12

निम्नलिखित उदाहरण देखें, जो प्रयास-अपवाद-के बारे में सब कुछ बताता है-आखिरकार:

for i in range(3):
    try:
        y = 1 / i
    except ZeroDivisionError:
        print(f"\ti = {i}")
        print("\tError report: ZeroDivisionError")
    else:
        print(f"\ti = {i}")
        print(f"\tNo error report and y equals {y}")
    finally:
        print("Try block is run.")

इसे लागू करें और इसके द्वारा आएं:

    i = 0
    Error report: ZeroDivisionError
Try block is run.
    i = 1
    No error report and y equals 1.0
Try block is run.
    i = 2
    No error report and y equals 0.5
Try block is run.

3
यह एक महान, सरल उदाहरण है जो एक लंबी सार व्याख्या को पढ़ने के लिए किसी (जो बहुत जल्दी में हो सकता है) की आवश्यकता के बिना जल्दी से पूर्ण प्रयास खंड को प्रदर्शित करता है। (बेशक, जब वे अब जल्दी में नहीं हैं, तो उन्हें वापस आना चाहिए और पूरा सार पढ़ना चाहिए।)
GlobalSoftwareSociety

6

आपको अंत में ब्लॉक का उपयोग करने के बारे में सावधान रहना चाहिए, क्योंकि यह एक और ब्लॉक का उपयोग करने की कोशिश में एक ही चीज नहीं है, सिवाय इसके। सिवाय प्रयास के परिणाम की परवाह किए बिना अंत में ब्लॉक चलाया जाएगा।

In [10]: dict_ = {"a": 1}

In [11]: try:
   ....:     dict_["b"]
   ....: except KeyError:
   ....:     pass
   ....: finally:
   ....:     print "something"
   ....:     
something

जैसा कि सभी ने उल्लेख किया है कि अन्य ब्लॉक का उपयोग करने से आपका कोड अधिक पठनीय हो जाता है, और केवल तब ही चलता है जब अपवाद नहीं फेंका जाता है

In [14]: try:
             dict_["b"]
         except KeyError:
             pass
         else:
             print "something"
   ....:

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

@ जुआन एंटोनियो गोमेज़ मोरियानो, मेरा कोडिंग ब्लॉक केवल उदाहरण के लिए है। मैं शायद कभी भी पास का उपयोग नहीं करता
ग्रेग

4

जब भी आप इसे देखें:

try:
    y = 1 / x
except ZeroDivisionError:
    pass
else:
    return y

या यहां तक ​​कि:

try:
    return 1 / x
except ZeroDivisionError:
    return None

इसके बजाय इस पर विचार करें:

import contextlib
with contextlib.suppress(ZeroDivisionError):
    return 1 / x

1
यह मेरे प्रश्न का उत्तर नहीं देता है, क्योंकि यह एक उदाहरण मात्र मेरा मित्र था।
जुआन एंटोनियो गोमेज़ मोरियानो

पायथन में, अपवाद त्रुटियां नहीं हैं। वे असाधारण भी नहीं हैं। पायथन में, प्रवाह नियंत्रण के अपवादों का उपयोग करना सामान्य और स्वाभाविक है। यह मानक पुस्तकालय में Referencelib.suppress () के समावेश से स्पष्ट है। रेमंड हेटिंगर के उत्तर को यहां देखें: stackoverflow.com/a/16138864/1197429 (रेमंड एक कोर पायथन योगदानकर्ता है, और सभी चीजों पर अधिकार पायथोनिक!)
राजीव बकुलेश शाह

4

सिर्फ इसलिए कि किसी और ने इस राय को पोस्ट नहीं किया है, मैं कहूंगा

elseक्‍लॉज से बचें try/excepts क्‍योंकि वे अधिकांश लोगों से अपरिचित हैं

कीवर्ड के विपरीत try, exceptहै, और finally, के अर्थ elseखंड नहीं स्वयं स्पष्ट है; यह कम पठनीय है। क्योंकि यह बहुत बार उपयोग नहीं किया जाता है, इसलिए यह उन लोगों का कारण बनेगा जो आपके कोड को पढ़ने के लिए डॉक्स को दोबारा जांचना चाहते हैं, सुनिश्चित करें कि वे समझ रहे हैं कि क्या चल रहा है।

(मैं इस उत्तर को ठीक-ठीक लिख रहा हूं क्योंकि मुझे try/except/elseमेरे कोडबेस में पाया गया और इसने एक wtf पल का कारण बना और मुझे कुछ गोगो करने के लिए मजबूर किया)।

इसलिए, जहाँ भी मुझे ओपी उदाहरण जैसा कोड दिखाई देता है:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
else:
    # do some more processing in non-exception case
    return something

मैं रिफ्लेक्टर करना पसंद करूंगा

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    return  # <1>
# do some more processing in non-exception case  <2>
return something
  • <1> स्पष्ट वापसी, स्पष्ट रूप से दिखाता है कि अपवाद मामले में, हम काम कर रहे हैं

  • <2> एक अच्छा मामूली साइड-इफेक्ट के रूप में, जो कोड elseब्लॉक में हुआ करता था, वह एक स्तर द्वारा काटा जाता है।


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

2

यह मेरी सरल स्निपेट है कि पाइथन में अंततः प्रयास-अपवाद-और-ब्लॉक को कैसे समझा जाए:

def div(a, b):
    try:
        a/b
    except ZeroDivisionError:
        print("Zero Division Error detected")
    else:
        print("No Zero Division Error")
    finally:
        print("Finally the division of %d/%d is done" % (a, b))

आइए div 1/1 का प्रयास करें:

div(1, 1)
No Zero Division Error
Finally the division of 1/1 is done

आइए div 1/0 की कोशिश करते हैं

div(1, 0)
Zero Division Error detected
Finally the division of 1/0 is done

1
मुझे लगता है कि यह इस बात की छूट देने में विफल है कि आप कोशिश के अंदर दूसरा कोड क्यों नहीं डाल सकते हैं
Mojimi

-4

ओपी, आप सही हैं। पायथन में सिवाय कोशिश / बदसूरत के बाद अन्य है । यह एक अन्य प्रवाह-नियंत्रण वस्तु की ओर जाता है, जहाँ किसी की आवश्यकता नहीं है:

try:
    x = blah()
except:
    print "failed at blah()"
else:
    print "just succeeded with blah"

एक पूरी तरह से स्पष्ट समकक्ष है:

try:
    x = blah()
    print "just succeeded with blah"
except:
    print "failed at blah()"

यह अन्य क्लॉज की तुलना में कहीं अधिक स्पष्ट है। कोशिश के अलावा / अक्सर लिखा नहीं जाता है, इसलिए यह समझने में एक पल लगता है कि निहितार्थ क्या हैं।

सिर्फ इसलिए कि आप एक काम कर सकते हैं, इसका मतलब यह नहीं है कि आप एक काम करें।

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

बस मेरे 5 सेंट यहाँ। मुझे कॉलेज के डेवलपर्स द्वारा लिखे गए 1-वर्षीय द्वारा लिखे गए बहुत सारे कोड को पीछे छोड़ना और साफ़ करना है, जो सोचते हैं कि वे स्मार्ट हैं और कुछ uber- तंग, uber- कुशल तरीके से कोड लिखना चाहते हैं जब वह इसे गड़बड़ करता है कोशिश करना और बाद में पढ़ना / संशोधित करना। मैं हर दिन और दो बार रविवार को पठनीयता के लिए मतदान करता हूं।


15
आप सही हे। यह पूरी तरह से स्पष्ट और समतुल्य है ... जब तक कि यह आपका printकथन विफल न हो। यदि कोई x = blah()रिटर्न देता है तो क्या होता है str, लेकिन आपका प्रिंट स्टेटमेंट क्या है print 'just succeeded with blah. x == %d' % x? अब आपको एक ऐसा TypeErrorजनरेट मिल रहा है, जहाँ आप एक को संभालने के लिए तैयार नहीं हैं; आप x = blah()अपवाद का स्रोत खोजने के लिए निरीक्षण कर रहे हैं , और यह वहां भी नहीं है। मैंने यह (या समतुल्य) एक से अधिक बार किया है, जहाँ elseमुझे यह गलती करने से रोक दिया होगा। अब मैं बेहतर जानता हूं। :
डग आर।

2
... और हां, आप सही कह रहे हैं। elseखंड एक सुंदर बयान नहीं है, और जब तक आप इसे करने के लिए इस्तेमाल कर रहे हैं, यह सहज नहीं है। लेकिन तब, न तो finallyजब मैंने पहली बार इसका इस्तेमाल शुरू किया था ...
डग आर।

2
डौग आर। को प्रतिध्वनित करने के लिए, यह समतुल्य नहीं है क्योंकि elseखंड में कथनों के दौरान अपवादों को पकड़ा नहीं जाता है except
एलेस्टेयर

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

1
@DougR। "आप x = blah()अपवाद के स्रोत का पता लगाने के लिए निरीक्षण कर रहे हैं ", tracebackआप एक गलत जगह से अपवाद स्रोत का निरीक्षण क्यों करेंगे?
नेहेम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.