ऊपर अर्मिन रोनाचेर का सटीक स्पष्टीकरण, उनके उत्तरों पर विस्तार करते हुए ताकि मेरे जैसे शुरुआती इसे अच्छी तरह से समझें:
एक वर्ग में परिभाषित विधियों में अंतर, चाहे स्थिर या उदाहरण विधि (वहाँ अभी तक एक और प्रकार है - वर्ग विधि - यहां चर्चा नहीं की गई है इसलिए इसे छोड़ देना), इस तथ्य में निहित है कि क्या वे किसी तरह वर्ग उदाहरण के लिए बाध्य हैं या नहीं। उदाहरण के लिए, यह कहें कि रनटाइम के दौरान विधि को क्लास के उदाहरण का संदर्भ मिलता है या नहीं
class C:
a = []
def foo(self):
pass
C # this is the class object
C.a # is a list object (class property object)
C.foo # is a function object (class property object)
c = C()
c # this is the class instance
__dict__क्लास ऑब्जेक्ट की डिक्शनरी प्रॉपर्टी एक क्लास ऑब्जेक्ट के सभी गुणों और तरीकों का संदर्भ रखती है और इस प्रकार
>>> C.__dict__['foo']
<function foo at 0x17d05b0>
विधि फू ऊपर के रूप में सुलभ है। यहां ध्यान देने वाली एक महत्वपूर्ण बात यह है कि अजगर में सब कुछ एक वस्तु है और इसलिए ऊपर दिए गए शब्दकोश में संदर्भ स्वयं अन्य वस्तुओं की ओर इशारा करते हैं। मुझे क्लास प्रॉपर्टी ऑब्जेक्ट्स - या सीपीओ के रूप में संक्षिप्तता के लिए मेरे उत्तर के दायरे में बुलाते हैं।
यदि CPO एक डिस्क्रिप्टर है, तो अजगर व्याख्याकार कॉल करता है __get__() सीपीओ विधि को उस मूल्य तक पहुंचने के लिए ।
यह निर्धारित करने के लिए कि क्या सीपीओ एक डिस्क्रिप्टर है, अजगर व्याख्याकार जाँच करता है कि क्या यह डिस्क्रिप्टर प्रोटोकॉल को लागू करता है। डिस्क्रिप्टर प्रोटोकॉल को लागू करने के लिए 3 तरीकों को लागू करना है
def __get__(self, instance, owner)
def __set__(self, instance, value)
def __delete__(self, instance)
उदाहरण के लिए
>>> C.__dict__['foo'].__get__(c, C)
कहाँ पे
self CPO है (यह सूची, str, फ़ंक्शन आदि का एक उदाहरण हो सकता है) और रनटाइम द्वारा आपूर्ति की जाती है
instance उस वर्ग का उदाहरण है जहां इस CPO को परिभाषित किया गया है (ऊपर 'ऑब्जेक्ट' c ') और हमारे द्वारा आपूर्ति की जाने वाली खोज की आवश्यकता है
ownerवह वर्ग है जहाँ इस CPO को परिभाषित किया गया है (ऊपर कक्षा वस्तु 'C') और हमारे द्वारा आपूर्ति की जानी चाहिए। हालाँकि ऐसा इसलिए है क्योंकि हम इसे CPO पर बुला रहे हैं। जब हम इसे उदाहरण पर कहते हैं, तो हमें इसकी आपूर्ति करने की आवश्यकता नहीं है क्योंकि रनटाइम इंस्टेंस या इसके वर्ग (बहुरूपता) की आपूर्ति कर सकता है
value सीपीओ के लिए इच्छित मूल्य है और हमारे द्वारा आपूर्ति की जानी चाहिए
सभी सीपीओ डिस्क्रिप्टर नहीं हैं। उदाहरण के लिए
>>> C.__dict__['foo'].__get__(None, C)
<function C.foo at 0x10a72f510>
>>> C.__dict__['a'].__get__(None, C)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__get__'
इसका कारण यह है कि सूची वर्ग वर्णनकर्ता प्रोटोकॉल को लागू नहीं करता है।
इस प्रकार तर्क स्वयं c.foo(self)की आवश्यकता है क्योंकि इसकी विधि हस्ताक्षर वास्तव में यही हैC.__dict__['foo'].__get__(c, C) (जैसा कि ऊपर बताया गया है, सी की आवश्यकता नहीं है क्योंकि यह पता लगाया जा सकता है या बहुरूपित हो सकता है) और यही कारण है कि यदि आप उस आवश्यक उदाहरण तर्क को पास नहीं करते हैं तो आपको टाइपऑवर मिलता है।
यदि आप नोटिस करते हैं कि विधि अभी भी क्लास ऑब्जेक्ट सी के माध्यम से संदर्भित है और क्लास के उदाहरण के साथ बाइंडिंग को इस फ़ंक्शन में इंस्टेंस ऑब्जेक्ट के रूप में एक संदर्भ पास करने के माध्यम से प्राप्त किया जाता है।
यह बहुत बढ़िया है क्योंकि यदि आपने कोई संदर्भ या उदाहरण के लिए कोई बंधन नहीं रखा है, तो यह आवश्यक है कि सभी को वर्णनकर्ता सीपीओ को लपेटने के लिए एक वर्ग लिखना चाहिए और __get__()बिना संदर्भ के इसकी विधि को ओवरराइड करना चाहिए। यह नया वर्ग है जिसे हम डेकोरेटर कहते हैं और कीवर्ड के माध्यम से लागू किया जाता है@staticmethod
class C(object):
@staticmethod
def foo():
pass
नए लिपटे सीपीओ में संदर्भ की अनुपस्थिति fooएक त्रुटि फेंकती है और निम्नानुसार सत्यापित की जा सकती है:
>>> C.__dict__['foo'].__get__(None, C)
<function foo at 0x17d0c30>
स्थैतिक विधि का उपयोग एक नाम स्थान और कोड में स्थिरता एक से अधिक है (इसे एक वर्ग से बाहर ले जाना और इसे मॉड्यूल आदि में उपलब्ध कराना)।
जब तक संभव हो, उदाहरण के तरीकों के बजाय स्थिर तरीकों को लिखना बेहतर होगा, जब तक कि संभोग करने के लिए आपको तरीकों का उपयोग करने की आवश्यकता न हो (जैसे कि पहुंच आवृत्ति चर, वर्ग चर आदि)। एक कारण वस्तुओं के अवांछित संदर्भ न रखकर कचरा संग्रह को कम करना है।