पाइथन - अगर बनाम लौटा और लौटा


12

मैं एक स्क्रिप्ट लिख रहा हूं जो एक पाठ फ़ाइल के लिए कुछ करता है (यह क्या करता है, हालांकि मेरे प्रश्न के लिए अप्रासंगिक है)। तो इससे पहले कि मैं फ़ाइल के लिए कुछ करूँ मैं जाँच करना चाहता हूँ कि क्या फ़ाइल मौजूद है। मैं यह कर सकता हूं, कोई बात नहीं, लेकिन मुद्दा सौंदर्यशास्त्र का है।

यहां मेरा कोड है, एक ही चीज़ को दो अलग-अलग तरीकों से लागू करना।

def modify_file(filename):
    assert os.path.isfile(filename), 'file does NOT exist.'


Traceback (most recent call last):
  File "clean_files.py", line 15, in <module>
    print(clean_file('tes3t.txt'))
  File "clean_files.py", line 8, in clean_file
    assert os.path.isfile(filename), 'file does NOT exist.'
AssertionError: file does NOT exist.

या:

def modify_file(filename):
    if not os.path.isfile(filename):
        return 'file does NOT exist.'


file does NOT exist.

पहली विधि एक आउटपुट का उत्पादन करती है जो ज्यादातर तुच्छ है, केवल एक चीज जिसकी मुझे परवाह है कि फाइल मौजूद नहीं है।

दूसरी विधि एक स्ट्रिंग लौटाती है, यह सरल है।

मेरा प्रश्न है: उपयोगकर्ता को यह बताने के लिए कौन सी विधि बेहतर है कि फ़ाइल मौजूद नहीं है? assertविधि का उपयोग किसी भी तरह से अधिक pythonic लगता है।

जवाबों:


33

आप इसके बजाय एक तीसरे विकल्प के साथ जाएंगे : उपयोग raiseऔर एक विशिष्ट अपवाद। यह अंतर्निहित अपवादों में से एक हो सकता है , या आप नौकरी के लिए एक कस्टम अपवाद बना सकते हैं।

इस मामले में, मैं उपयोग करूँगा IOError, लेकिन ValueErrorयह भी फिट हो सकता है:

def modify_file(filename):
    if not os.path.isfile(filename):
        raise IOError('file does NOT exist.')

एक विशिष्ट अपवाद का उपयोग करने से आप अलग-अलग असाधारण परिस्थितियों के लिए अन्य अपवादों को उठा सकते हैं, और कॉलर को इनायत से अपवाद को संभालने देता है।

बेशक, कई फ़ाइल संचालन (जैसे open()) खुद को OSErrorपहले से ही बढ़ाते हैं ; यदि फ़ाइल मौजूद है तो स्पष्ट रूप से पहला परीक्षण यहां निरर्थक हो सकता है।

उपयोग न करें assert; यदि आप -Oध्वज के साथ अजगर को चलाते हैं , तो कोड से सभी दावे छीन लिए जाते हैं।


अतिरेक के बारे में दिलचस्प बात! क्या आप इससे बचने की सलाह देंगे? यानी "यह वैसे भी बाद में विफल हो जाएगा"
सिप्रियन टॉमोयागॉ

1
@ CiprianTomoiagă: परीक्षणों पर डबल क्यों? यदि अगली पंक्ति modify_file()है with open(filename) as f:, तो IOErrorभी उठाया जाएगा। और अधिक हाल के पायथन संस्करणों ने IOError( FileNotFoundErrorविशेष रूप से मन में आता है) के उपवर्गों में अधिक विस्तार प्रदान किया है जो इस एपीआई का उपयोग करने वाले डेवलपर के लिए सहायक हो सकता है। यदि कोड स्वयं जाँच करता है और उठाता है IOErrorतो वह सहायक विवरण खो जाएगा।
Martijn Pieters

@MartijnPieters का एक स्वीकार्य जवाब होगा "परीक्षणों पर दोहरी मार क्यों?" जब खुला () विफल होने पर उठाए गए अपवाद की तुलना में पहला चेक तेज़ हो तो कब होगा? उदाहरण के लिए, जब फ़ाइल के अस्तित्व की जाँच करना खोलने की कोशिश करने और अंततः ऐसा करने में विफल रहने की तुलना में तेज़ हो।
मार्सेल विल्सन

1
@ मार्सेलविल्सन: नहीं, क्योंकि आप एक ऐसी विधि के खिलाफ सूक्ष्म-अनुकूलन कर रहे होंगे जो I / O करता है। पाइथन शब्दार्थ में मिनट की कोई ट्विकिंग आई / ओ को तेज नहीं बनाती है, और केवल पठनीयता और स्थिरता को नुकसान पहुंचाती है। अधिक प्रभाव वाले क्षेत्रों पर ध्यान दें, मैं कहूंगा।
मार्टिजन पीटरर्स

12

assertउन मामलों के लिए अभिप्रेत है जहाँ प्रोग्रामर को कॉल करने वाले ने गलती की, उपयोगकर्ता के विपरीत । assertउस परिस्थिति में उपयोग करना आपको यह सुनिश्चित करने की अनुमति देता है कि परीक्षण के दौरान एक प्रोग्रामर आपके फ़ंक्शन का सही उपयोग कर रहा है, लेकिन फिर इसे उत्पादन में पट्टी कर दें।

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

आपके विशेष मामले में, एक लापता फ़ाइल लगभग निश्चित रूप से एक उपयोगकर्ता त्रुटि है, और एक अपवाद को उठाकर नियंत्रित किया जाना चाहिए।


5

से UsingAssertionsEffectively

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

स्थान डालने पर विचार करने के लिए स्थान:

checking parameter types, classes, or values
checking data structure invariants
checking "can't happen" situations (duplicates in a list, contradictory state variables.)
after calling a function, to make sure that its return is reasonable 

समग्र बिंदु यह है कि अगर कुछ गलत होता है, तो हम इसे जल्द से जल्द पूरी तरह से स्पष्ट करना चाहते हैं।

यह उस बिंदु पर गलत डेटा को पकड़ना आसान है जहां यह काम करने की तुलना में चला जाता है कि बाद में यह कैसे हो गया जब यह परेशानी का कारण बनता है।

अभिकथन इकाई परीक्षणों या सिस्टम परीक्षणों का विकल्प नहीं है, बल्कि एक पूरक है। क्योंकि दावे किसी वस्तु या कार्य की आंतरिक स्थिति की जांच करने का एक साफ तरीका है, वे बाहरी व्यवहार की जांच करने वाले ब्लैक-बॉक्स परीक्षण के लिए एक स्पष्ट-बॉक्स सहायता के लिए "मुफ्त में" प्रदान करते हैं।

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

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

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