कार्यों में अपवाद बनाम वापसी को बढ़ाएं?


85

पायथन में उपयोगकर्ता-परिभाषित फ़ंक्शन में बेहतर अभ्यास क्या है: raiseएक अपवाद या return None? उदाहरण के लिए, मेरे पास एक फ़ंक्शन है जो एक फ़ोल्डर में सबसे हाल की फ़ाइल पाता है।

def latestpdf(folder):
    # list the files and sort them
    try:
        latest = files[-1]
    except IndexError:
        # Folder is empty.
        return None  # One possibility
        raise FileNotFoundError()  # Alternative
    else:
        return somefunc(latest)  # In my case, somefunc parses the filename

एक अन्य विकल्प अपवाद छोड़ रहा है और इसे कॉलर कोड में संभाल सकता है, लेकिन मुझे लगता है कि यह एक FileNotFoundErrorसे अधिक से निपटने के लिए अधिक स्पष्ट है IndexError। या एक अलग नाम के साथ एक अपवाद को फिर से बढ़ाने के लिए यह बुरा रूप है?



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

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

जवाबों:


91

यह वास्तव में शब्दार्थ की बात है। क्या foo = latestpdf(d) मतलब है ?

क्या यह पूरी तरह से उचित है कि कोई नवीनतम फ़ाइल नहीं है? फिर यकीन है, बस कोई नहीं लौटा।

क्या आप हमेशा एक नवीनतम फ़ाइल खोजने की उम्मीद कर रहे हैं? एक अपवाद उठाएं। और हाँ, अधिक उपयुक्त अपवाद को फिर से उठाना ठीक है।

यदि यह केवल एक सामान्य कार्य है जिसे किसी भी निर्देशिका में लागू किया जाना है, तो मैं पूर्व करूंगा और कोई नहीं लौटाऊंगा। यदि निर्देशिका है, उदाहरण के लिए, एक विशिष्ट डेटा निर्देशिका होने का मतलब है जिसमें किसी एप्लिकेशन के ज्ञात सेट शामिल हैं, तो मैं एक अपवाद बढ़ाऊंगा।


3
विचार करने के लिए एक और बिंदु: यदि एक अपवाद को बढ़ाने से एक संदेश संलग्न किया जा सकता है, लेकिन हम वापसी करते समय ऐसा नहीं कर सकते None
kawing-chiu

9

मैं आपके प्रश्न का उत्तर देने से पहले कुछ सुझाव दूंगा क्योंकि यह आपके लिए प्रश्न का उत्तर दे सकता है।

  • हमेशा अपने कार्यों को वर्णनात्मक नाम दें। latestpdfकिसी के लिए बहुत कम मतलब है, लेकिन अपने कार्य latestpdf()को देखने से नवीनतम पीडीएफ मिलता है। मेरा सुझाव है कि आप इसे नाम दें getLatestPdfFromFolder(folder)

जैसे ही मैंने ऐसा किया, यह स्पष्ट हो गया कि इसे क्या लौटना चाहिए .. अगर कोई pdf अपवाद नहीं है। लेकिन वहां और इंतजार करें ..

  • कार्यों को स्पष्ट रूप से परिभाषित रखें। चूंकि यह स्पष्ट नहीं है कि कोई व्यक्ति क्या करना चाहता है और यह (जाहिरा तौर पर) स्पष्ट नहीं है कि यह नवीनतम पीडीएफ प्राप्त करने से संबंधित है जो मैं आपको इसे स्थानांतरित करने का सुझाव दूंगा। यह कोड को और अधिक पठनीय बनाता है।

for folder in folders:
   try:
       latest = getLatestPdfFromFolder(folder)
       results = somefuc(latest)
   except IOError: pass

उम्मीद है की यह मदद करेगा!


या get_latest_pdf_from_folder। वास्तव में, Pep8: "फ़ंक्शन नाम कम होना चाहिए, पठनीयता में सुधार के लिए आवश्यक रूप से अंडरस्कोर द्वारा अलग किए गए शब्दों के साथ।"
पैट्रिकटी

7

मैं आमतौर पर अपवादों को आंतरिक रूप से संभालना पसंद करता हूं (अर्थात कोशिश की गई फ़ंक्शन के अंदर को छोड़कर, संभवतः कोई नहीं लौटाता) क्योंकि अजगर गतिशील रूप से टाइप किया गया है। सामान्य तौर पर, मैं इसे एक तरह से या दूसरे तरीके से कॉल करने वाला निर्णय मानता हूं, लेकिन गतिशील रूप से टाइप की गई भाषा में, ऐसे छोटे कारक होते हैं जो कॉल करने वाले को अपवाद नहीं पारित करने के पक्ष में तराजू को टिप देते हैं:

  1. आपके फ़ंक्शन को कॉल करने वाले किसी भी व्यक्ति को उन अपवादों के बारे में सूचित नहीं किया जाता है जिन्हें फेंक दिया जा सकता है। यह जानने के लिए कि आप किस तरह के अपवाद का शिकार हो रहे हैं (और सामान्य से हटकर किए जाने वाले ब्लॉकों को छोड़कर) किस तरह का एक कला रूप हो जाता है।
  2. if val is Noneकी तुलना में थोड़ा आसान है except ComplicatedCustomExceptionThatHadToBeImportedFromSomeNameSpace। सच में, मैं from django.core.exceptions import ObjectDoesNotExistअपने सभी django फ़ाइलों के शीर्ष पर टाइप करने के लिए याद रखने से नफरत करता हूँ बस एक बहुत ही सामान्य उपयोग के मामले को संभालने के लिए। वैधानिक रूप से टाइप की गई दुनिया में, संपादक को इसे आपके लिए करने दें।

ईमानदारी से, हालांकि, यह हमेशा एक निर्णय कॉल है, और जिस स्थिति का आप वर्णन कर रहे हैं, जहां एक फ़ंक्शन को एक त्रुटि प्राप्त होती है जो इसे मदद नहीं कर सकती है, यह एक अपवाद को फिर से बढ़ाने का एक उत्कृष्ट कारण है जो सार्थक है। आपके पास सटीक सही विचार है, लेकिन जब तक आप अपवाद नहीं हैं, तब तक स्टैक ट्रेस में अधिक सार्थक जानकारी प्रदान करने जा रहे हैं

AttributeError: 'NoneType' object has no attribute 'foo'

जो, दस में से नौ बार है, अगर आप किसी को न लौटाने वाले को वापस बुलाते हैं, तो फोन करने वाला आपको परेशान नहीं करेगा।

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


यह तर्क कि संभावित अपवादों को परिभाषित नहीं किया गया है और इसलिए इसे पकड़ना कठिन है, पायथन के लिए बहुत वैध तर्क है।
स्नोबुर्हिस

4

अजगर 3.5 टाइपिंग के साथ :

उदाहरण समारोह जब कोई नहीं लौटेगा:

def latestpdf(folder: str) -> Union[str, None]

और जब एक अपवाद होगा:

def latestpdf(folder: str) -> str 

विकल्प 2 अधिक पठनीय और पाइथोनिक लगता है

(जैसा कि पहले कहा गया था, अपवाद को टिप्पणी जोड़ने का विकल्प।)


4
Union[str, None]होना चाहिएOptional[str]
जार्ज

2
एक आशुलिपि, लेकिन आप सही हैं, यह अधिक पठनीय है। संपादन नहीं तो दोनों विकल्प यहाँ हैं।
आसफ

2 संभावित रूप से अधिक पठनीय है लेकिन (दुर्भाग्य से?) प्रकार के संकेत यह नहीं दर्शाते हैं कि एक अपवाद को फेंक दिया जा सकता है। मैंने हाल ही में पाया है कि 1 अधिक त्रुटियों को पकड़ने में मदद करेगा क्योंकि आप किसी भी रिटर्न को संभालने के लिए मजबूर नहीं होते हैं।
jonespm

2

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

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