2012-10-11 13 views
9

संभव डुप्लिकेट:
When and why might I assign an instance of a descriptor class to a class attribute in Python rather than use a property?अजगर वर्णनकर्ता बनाम संपत्ति

मैं जब एक विवरणक बनाम एक संपत्ति का उपयोग करने के लिए के रूप में उलझन में हूँ। मैंने पढ़ा कि एक संपत्ति एक विशेष वर्णनकर्ता है।

क्या कोई यह पोस्ट कर सकता है कि यह कैसे काम करता है?

उत्तर

12

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

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

+0

यह ध्यान देने योग्य है कि अजगर जहां आवश्यक को छोड़कर getters और setters के उपयोग को हतोत्साहित ... लायक हो सकता है या यह नहीं हो सकता .. –

+3

@ जोरन बेस्ले यह पूरी तरह से अनावश्यक के रूप में ज्यादा निराश नहीं है। चूंकि पाइथन आपको विशेषता पहुंच को ओवरराइड करने देता है, इसलिए आप यह तय कर सकते हैं कि आपको उप-वर्ग में इसकी आवश्यकता है। यदि आपको गणना की गई संपत्ति की आवश्यकता है, तो गेटटर का उपयोग करना उचित है। जावा/सी # में, आपको आगे तय करने की आवश्यकता है कि क्या आप एक विशिष्ट विशेषता तक पहुंच को ओवरराइड करने की अनुमति देना चाहते हैं, और कक्षा पदानुक्रम के शीर्ष पर इसे प्रदान करना चाहते हैं। यही कारण है कि संपत्तियों का व्यापक रूप से उपयोग करना आम है: यह "बस मामले में" किया जाता है। – millimoose

9

आप here दोनों के बारे में अधिक पढ़ सकते हैं। लेकिन यहां एक ही पुस्तक से एक साधारण उदाहरण है जो अलग-अलग हल करने की कोशिश करता है जो एक ही समस्या है। जैसा कि आप देख सकते हैं, गुणों का उपयोग कर कार्यान्वयन बहुत आसान है।

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

संपत्ति समारोह हमें एक अलग वर्ग को परिभाषित किए बिना एक सरल वर्णनकर्ता को लागू करने का एक आसान तरीका प्रदान करता है। एक पूर्ण श्रेणी परिभाषा बनाने के बजाय, हम गेटर और सेटर विधि फ़ंक्शन लिख सकते हैं, और फिर इन फ़ंक्शंस को एक विशेषता नाम पर बाध्य कर सकते हैं।

डिस्क्रिप्टर उदाहरण:

class Celsius(object): 
    def __init__(self, value=0.0): 
     self.value= float(value) 
    def __get__(self, instance, owner): 
     return self.value 
    def __set__(self, instance, value): 
     self.value= float(value) 

class Farenheit(object): 
    def __get__(self, instance, owner): 
     return instance.celsius * 9/5 + 32 
    def __set__(self, instance, value): 
     instance.celsius= (float(value)-32) * 5/9 

class Temperature(object): 
    celsius= Celsius() 
    farenheit= Farenheit() 
>>> 
oven= Temperature() 
>>> 
oven.farenheit= 450 
>>> 
oven.celsius 
232.22222222222223 
>>> 
oven.celsius= 175 
>>> 
oven.farenheit 
347.0 

संपत्ति उदाहरण:

class Temperature(object): 
    def fget(self): 
     return self.celsius * 9/5 + 32 
    def fset(self, value): 
     self.celsius= (float(value)-32) * 5/9 
    farenheit= property(fget, fset) 
    def cset(self, value): 
     self.cTemp= float(value) 
    def cget(self): 
     return self.cTemp 
    celsius= property(cget, cset, doc="Celsius temperature") 
>>> 
oven= Temperature() 
>>> 
oven.farenheit= 450 
>>> 
oven.celsius 
232.22222222222223 
>>> 
oven.celsius= 175 
>>> 
oven.farenheit 
347.0 
+12

मेरा मानना ​​है कि सेल्सियस का आपका वर्णनकर्ता कार्यान्वयन सही नहीं है।आपको सेल्सियस को 'self' के बजाय' instance' पर सेट करना चाहिए था; यदि आप दो तापमान वस्तुएं बनाते हैं तो वे समान सेल्सियस मान साझा करेंगे। –

+0

मैंने 'वर्णनकर्ता उदाहरण' कोड चलाया और यह ठीक काम करता है। लेकिन मुझे समझ में नहीं आया कि 'example.celsius'' फारेनहाइट 'वर्ग में कैसे पहुंच योग्य है। धन्यवाद। – has