2015-12-28 6 views
8

contextlib.py में, मैं देख रहा हूँ ExitStack वर्ग प्रकार वस्तु (type(cm)) के माध्यम से __enter__() विधि बुला रहा है के बजाय प्रत्यक्ष विधि दिया वस्तु (cm) करने के लिए कहता है।क्यों टाइप करें (एक्स) .__ `x .__ के बजाय __ (x) 'दर्ज करें __()` पायथन मानक संदर्भ में दर्ज करें?

मुझे आश्चर्य है कि क्यों या क्यों नहीं।

जैसे

  • बेहतर अपवाद निशान एक त्रुटि तब होती है जब देता है?
  • क्या यह कुछ मॉड्यूल लेखक की कोडिंग शैली के लिए विशिष्ट है?
  • क्या इसका कोई प्रदर्शन लाभ है?
  • क्या यह जटिल प्रकार पदानुक्रमों के साथ कुछ कलाकृतियों/दुष्प्रभावों से बचता है?

उत्तर

12

सबसे पहले, यह क्या होता है जब आप with something करते हैं, यह सिर्फ contextlib उस प्रकार पर विशेष विधि की खोज करता है नहीं है। साथ ही, यह ध्यान देने योग्य है कि यह भी अन्य विशेष तरीकों के साथ होता है: उदा। a + b परिणाम type(a).__add__(a, b) में परिणाम।

लेकिन ऐसा क्यों होता है? यह एक प्रश्न है जिसे अक्सर पाइथन-देव और पायथन-विचार मेलिंग सूचियों पर निकाल दिया जाता है। और जब मैं "अक्सर" कहता हूं, मेरा मतलब है "बहुत बार"।

आखिरी बार ये थे: Missing Core Feature: + - */| & do not call getattr और Eliminating special method lookup। विशेष तरीकों वस्तु के वर्ग पर स्लॉट्स, उदाहरण के गुण नहीं के रूप में के रूप में देखा जाता है -

वर्तमान व्यवहार डिज़ाइन द्वारा है:

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

(Source)

यह ध्यान देने योग्य है कि व्यवहार भी इससे ज्यादा जादुई है लायक है। कक्षा में देखा जाने पर भी, विशेष विशेष विधि लुकअप मेटाक्लास के __getattr__ और __getattribute__ बाईपास करता है। तो विशेष विधि लुकअप केवल एक साधारण लुकअप नहीं है जो उदाहरण के बजाए कक्षा पर शुरू होता है; यह एक पूरी तरह से जादू लुकअप है जो पर किसी भी स्तर पर सामान्य विशेषता-पहुंच-अनुकूलन हुक संलग्न नहीं करता है।

(Source)

यह व्यवहार भी संदर्भ दस्तावेज़ पर प्रलेखित है: Special method lookup है, जो कहते हैं:

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

संक्षेप में, प्रदर्शन मुख्य चिंता है। लेकिन चलो इस पर एक नज़र डालें।

type(obj).__enter__() और obj.__enter__() के बीच क्या अंतर है?

जब आप obj.attr लिखते हैं, type(obj).__getattribute__('attr') कॉल किया जाता है। __getattribute__() का डिफ़ॉल्ट कार्यान्वयन उदाहरण के शब्दकोश में attr (यानी obj.__dict__) और कक्षा नामस्थान में दिखता है और विफल रहता है, type(obj).__getattr__('attr') पर कॉल करता है।

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

+0

आपके उत्तर के लिए धन्यवाद। फिर भी, मुझे आश्चर्य है कि क्यों टाइप करें (ए) .__ __ (ए, बी) 'के बजाय 'ए .__ जोड़ें __ (बी)'। क्या वे समान नहीं हैं? – Achimnol

+1

@Achimnol: यदि आप 'a .__ add__'' को कुछ असाइन करते हैं तो वे समान नहीं होते हैं। – user2357112

+1

@Achimnol: मुझे लगता है कि मैंने उस प्रश्न का भी उत्तर दिया है, लेकिन कृपया मुझे बताएं कि क्या मैं बहुत अस्पष्ट था –

संबंधित मुद्दे