2010-01-23 12 views
13

निम्नलिखित वर्ग परिभाषाओंपायथन: कई संपत्तियां हैं, एक सेटर/गेटर

class of2010(object): 
    def __init__(self): 
     self._a = 1 
     self._b = 2 
     self._c = 3 

    def set_a(self,value): 
     print('setting a...') 
     self._a = value 
    def set_b(self,value): 
     print('setting b...') 
     self._b = value 
    def set_c(self,value): 
     print('setting c...') 
     self._c = value 
    a = property(fset=self.set_a) 
    b = property(fset=self.set_b) 
    c = property(fset=self.set_c) 

ध्यान दें कि set_[a|b|c]() एक ही बात करते हैं पर विचार करें। वहाँ एक रास्ता है परिभाषित:

def set_magic(self,value): 
    print('setting <???>...') 
    self._??? = value 

एक बार और एक के लिए इसका इस्तेमाल करते हैं, ख, ग के रूप में

a = property(fset=self.set_magic) 
b = property(fset=self.set_magic) 
c = property(fset=self.set_magic) 

उत्तर

20
def attrsetter(attr): 
    def set_any(self, value): 
    setattr(self, attr, value) 
    return set_any 

a = property(fset=attrsetter('_a')) 
b = property(fset=attrsetter('_b')) 
c = property(fset=attrsetter('_c')) 
+0

यह संपत्ति (fset = ...) है, लेकिन अन्यथा मैं ऐसा कुछ उपयोग करूंगा। – olt

+0

@olt: धन्यवाद, तय। –

1

इस प्रकार हो सकता है आप एक नजर डालें के लिए __setattr__(self, name, value)

देख रहे हैं here

2
class... 
def __setattr__(self, name, value): 
    print 'setting', name 
    self.__dict__[name] = value 

यही है।

+1

यह सलाह पुरानी है। Https://docs.python.org/2/reference/datamodel.html#customizing-attribute-access के अनुसार, "आवृत्ति शब्दकोश तक पहुंचने के बजाय, नए-शैली वर्गों के लिए, '__setattr__' को बेस क्लास विधि को कॉल करना चाहिए वही नाम, उदाहरण के लिए, 'ऑब्जेक्ट .__ setattr __ (स्वयं, नाम, मान) '।" ध्यान दें कि ओपी एक नई शैली की कक्षा का उपयोग कर रहा है। –

5

मुझे लगता है कि आपके सेटर्स बस एक संदेश लॉग करते हैं और फिर केवल मूल्य आवंटित करते हैं - वास्तव में, आपके स्वीकृत उत्तर बस मान निर्दिष्ट करता है। क्या आप इस पैटर्न का उपयोग कर रहे हैं क्योंकि यह किसी अन्य भाषा में स्वीकृत अभ्यास/परंपरागत बुद्धि है, शायद उसका नाम जिसका नाम "जे" से शुरू होता है? यदि ऐसा है, तो जानने के लिए कृपया कि यह वही डिजाइन करने के लिए pythonic दृष्टिकोण बहुत सरल है:

class Of2010(object): 
    def __init__(self): 
     self.a = 1 
     self.b = 2 
     self.c = 3 

नहीं करते कुछ भी नहीं setters, कोई मध्यवर्ती समारोह सिर्फ एक मान देना कहते हैं। "क्या आप कहते हैं? "सदस्य चर के लिए सार्वजनिक संपर्क? !!" खैर, हां वास्तव में।

क्लाइंट कोड के दृष्टिकोण से इन कक्षाओं को देखें। अपने वर्ग का उपयोग करने के लिए, ग्राहकों को एक वस्तु बनाने के लिए, और फिर संपत्ति आवंटित "एक" का उपयोग कर:

obj = Of2010() 
obj.a = 42 

उल्लेखनीय है, इस 5-लाइनर वर्ग मैं ऊपर पोस्ट के लिए ठीक उसी कोड है।

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

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

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

+0

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

+0

में अनावश्यक हैं, यदि यह प्रत्येक आमंत्रण पर एक नाम प्रिंट करने जितना आसान है, तो इसे केवल __init __() में एन्कोड न करें, जिसे हमेशा प्रत्येक उदाहरण द्वारा बुलाया जाता है? –

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