पायथन क्षमा बनाम अनुमति और बतख टंकण


44

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

try:
    x = foo.bar
except AttributeError:
    pass
else:
    do(x)

से बेहतर या बुरा

if hasattr(foo, "bar"):
    do(foo.bar)
else:
    pass

प्रदर्शन, पठनीयता, "पायथोनिक", या कुछ अन्य महत्वपूर्ण कारक के संदर्भ में?


17
वहाँ एक तीसरा विकल्प है, कुछ भी करने के लिए और एक बग के रूप में एक बार बिना किसी भी foo का इलाज नहीं है
जे।

मुझे याद है कि hasattrआंतरिक रूप से उस सटीक कोशिश / कैच को लागू किया गया है। निश्चित नहीं है अगर यह सच है ... (यह गुणों पर अलग तरह से कार्य करेगा, यह नहीं होगा? शायद मैं सोच रहा हूँ getattr..)
इज़काता

@ इज़काटा: का कार्यान्वयनhasattr सी-एपीआई के बराबर का उपयोग करता है getattr( Trueयदि सफल हो तो वापसी False), लेकिन सी में अपवादों को संभालना बहुत तेज़ है।
मार्टिज़न पीटर्स

2
मैंने मार्टिज़न के उत्तर को स्वीकार कर लिया है, लेकिन मैं यह जोड़ना चाहूंगा कि यदि आप एक विशेषता निर्धारित करने का प्रयास कर रहे हैं, तो आपको निश्चित रूप से कोशिश / कैच का उपयोग करने पर विचार करना चाहिए क्योंकि यह एक सेटर के बिना एक संपत्ति हो सकती है, जिस स्थिति में हैसट्रेट सही होगा , लेकिन यह अभी भी विशेषता को बढ़ाएगा।
डार्कफ्लिन

जवाबों:


60

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

दोनों दृष्टिकोण, मेरी राय में, समान रूप से मान्य हैं, कम से कम पठनीयता और पाइथोनिक-नेस के संदर्भ में। लेकिन अगर आपकी 90% वस्तुओं में वह विशेषता नहीं है जो barआपको दो दृष्टिकोणों के बीच एक अलग प्रदर्शन अंतर दिखाई देगा:

>>> import timeit
>>> def askforgiveness(foo=object()):
...     try:
...         x = foo.bar
...     except AttributeError:
...         pass
... 
>>> def askpermission(foo=object()):
...     if hasattr(foo, 'bar'):
...         x = foo.bar
... 
>>> timeit.timeit('testfunc()', 'from __main__ import askforgiveness as testfunc')
2.9459929466247559
>>> timeit.timeit('testfunc()', 'from __main__ import askpermission as testfunc')
1.0396890640258789

लेकिन अगर आपके वस्तुओं का 90% है विशेषता है, टेबल दिया गया है:

>>> class Foo(object):
...     bar = None
... 
>>> foo = Foo()
>>> timeit.timeit('testfunc(foo)', 'from __main__ import askforgiveness as testfunc, foo')
0.31336188316345215
>>> timeit.timeit('testfunc(foo)', 'from __main__ import askpermission as testfunc, foo')
0.4864199161529541

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

अंत में, timeitमॉड्यूल का कुछ रणनीतिक उपयोग सबसे तीखी बात हो सकती है जो आप कर सकते हैं।


1
कुछ हफ़्ते पहले मैंने यह सवाल पूछा था: programmers.stackexchange.com/questions/161798/…। वहाँ मैंने पूछा कि क्या शिथिल टाइप की हुई भाषाओं में आपको अतिरिक्त प्रकार के चेक काम करने पड़ते हैं, और मुझे लोगों ने बमबारी करते हुए कहा कि आप नहीं थे। पता है मैं तुम्हें देख रहा हूँ
ट्यूलेंस कोरडोवा

@ user1598390: जब आप एक एपीआई को परिभाषित करते हैं जो एक प्रकार के समरूप मिश्रण की अपेक्षा करता है, तो आपको कुछ परीक्षण करने होंगे। अधिकांश समय, आप नहीं। यह विशिष्ट क्षेत्र है जहाँ से आप एक पूरे के रूप में प्रतिमानों के बारे में नियम प्राप्त नहीं कर सकते, मुझे डर है।
मार्टिज़न पीटर्स

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

1
@ गैरेथ: यह उत्तर के उत्तरार्ध के लिए एक पैटर्न स्थापित करता है जहां मैं फ़ंक्शन-अंडर-टेस्ट के लिए एक तर्क में पास करता हूं।
Martijn Pieters

1
ध्यान दें कि hasattr, यह वास्तव में सी-अपी को एक कोशिश के बराबर करता है-वैसे भी हुड के अलावा, क्योंकि यह एकमात्र सामान्य तरीका है जो यह निर्धारित करता है कि पिथन में एक वस्तु की विशेषता है कि वह इसे एक्सेस करने की कोशिश करे।
user2357112

11

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

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


3

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

दूसरी ओर पठनीयता और सरलता, हमेशा एक प्रमुख चिंता का विषय है। यहां कोई कठिन नियम नहीं हैं, बस अपने निर्णय का उपयोग करें।

यह एक सार्वभौमिक मुद्दा है, लेकिन पर्यावरण- या भाषा-विशिष्ट सम्मेलन प्रासंगिक हैं। उदाहरण के लिए, पायथन में आमतौर पर यह ठीक होता है कि आप जिस विशेषता की उम्मीद करते हैं उसका उपयोग करें और कॉल करने वाले को एक संभावित एट्रीब्यूट तक पहुंचने दें।


-1

शुद्धता के संदर्भ में , मुझे लगता है कि अपवाद से निपटने का तरीका है (मैं कभी-कभी हॅटटर () स्वयं का उपयोग करता हूं, हालांकि)। Hasattr () पर भरोसा करने के साथ मूल समस्या यह है कि यह कोड अनुबंधों के उल्लंघन को मूक विफलताओं में बदल देता है (यह जावास्क्रिप्ट में एक बड़ी समस्या है, जो गैर-मौजूदा गुणों पर नहीं फेंकती है)।


3
आपका उत्तर दूसरों द्वारा पहले ही बताई गई बातों से अधिक नहीं जुड़ता है। अन्य साइटों के विपरीत, प्रोग्रामर उन उत्तरों की अपेक्षा करते हैं जो उत्तर के पीछे क्यों समझाते हैं । आप मौन विफलता मुद्दे के साथ एक अच्छे बिंदु को छूते हैं, लेकिन उसे न्याय नहीं देना चाहिए। निम्नलिखित पढ़ने से मदद मिल सकती है: programmers.stackexchange.com/help/how-to-answer

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