2014-09-26 4 views
7

मैं इस सवाल का जवाब देख रहा था: Is it possible to define a class constant inside an Enum?पायथन: लगातार क्लास

एतान फर्मन के जवाब में क्या दिलचस्पी मुझे लगातार वर्ग सबसे था।

class Constant: 
    def __init__(self, value): 
     self.value = value 
    def __get__(self, *args): 
     return self.value 
    def __repr__(self): 
     return '%s(%r)' % (self.__class__.__name__, self.value) 

प्रश्न पायथन 3.4 के बारे में था लेकिन मैं 2.7 का उपयोग कर रहा हूं। जवाब में एतान तो जैसे वर्ग ग्रह का एक उदाहरण चर के रूप में गुरुत्वाकर्षण स्थिरांक सेट:

G = Constant(6.67300E-11) 

2,7 में इस वर्ग की मेरे परीक्षण से पता चलता है कि टाइपिंग बस जी मुझे इस देता है:

Out[49]: Constant(3) 

(परीक्षण के दौरान मैंने इसे आसानी से उपयोग करने के लिए 3 पर सेट किया है। यह मुझे __repr__ आउटपुट जैसा दिखता है, अगर मैं गलत हूं तो कृपया मुझे सही करें।

मूल्य G.value के माध्यम से उपलब्ध है। हालांकि, एथन के जवाब में वह

का उपयोग करता है
return self.G * self.mass/(self.radius * self.radius) 

यह स्पष्ट रूप से केवल तभी काम करता है जब मान __repr__ आउटपुट बनाम लौटाया जाता है। अब अगर मैं class Constant: से class Constant(int): बदलता हूं तो जी टाइप करें मुझे अभी भी __repr__ आउटपुट मिलता है लेकिन यदि मैं G * 4 टाइप करता हूं तो मुझे 12 त्रुटि मिलती है जो मुझे मिल रही थी। (TypeError: *: 'instance' और 'int' के लिए असमर्थित ऑपरेंड प्रकार (0)

तो स्पष्ट रूप से कुछ ऑब्जेक्ट की तरह कुछ स्पष्ट रूप से कॉल किया जा सकता है। क्या कोई जादू विधि है जो मुझे याद आ रही है जो मुझे कॉन्स्टेंट क्लास के लिए ऐसा करने की अनुमति देगी? चूंकि स्थिरांक तार, पूर्णांक या फ्लोट हो सकते हैं, इसलिए मैं 1 वर्ग रखना पसंद करूंगा जो उन सभी वस्तुओं को बढ़ाकर 3 अलग-अलग वर्गों को संभालता है।

मूल्य G.value के माध्यम से भी सेटटेबल है। क्या मैं इसे बंद कर सकता हूं ताकि कॉन्स्टेंट क्लास व्यवहार को वास्तविक स्थिरता पसंद कर सके? (मुझे संदेह है कि उत्तर नहीं है।)

+0

आप इसे स्थिर क्यों रखना चाहते हैं? – Veedrac

+0

@Veedrac मैं कॉन्स्टेंट क्यों नहीं चाहूंगा? या केवल कक्षा के भीतर मूल्यों को पढ़ा? पायथन पर पढ़ने से, मैं समझता हूं कि यह पाइथन के "हम सब वयस्कों की सहमति कर रहे हैं" दर्शन का मुकाबला है। मुझे अब तक पाइथन पसंद है लेकिन मुझे लगता है कि दर्शन एक निरीक्षण है। मैं अपने लिए, खुद, और मैं प्रोग्राम - कोई और इसे पढ़ नहीं पाएगा या इसका उपयोग संभवतः करेगा। पिछले 15 वर्षों से कई भाषाओं में कोडिंग करने के बाद मैंने कुछ चीजें सीखी हैं। उन चीजों में से एक यह है कि मैं केवल कक्षा को डिजाइन करके डेबगिंग के दिनों को रोक सकता हूं जहां कुछ चीजें सिर्फ उस वर्ग के आंतरिक लोगों के बाहर नहीं बदला जा सकता है। –

+0

मैं और अधिक सोच रहा था कि आपको किस स्तर पर निरंतर रहने की आवश्यकता है; मेरा मुद्दा यह जांचना था कि क्या आप "सार्वजनिक इंटरफेस के माध्यम से निरंतर" के साथ ठीक थे, जो ऐसा करने का सही तरीका है, या आप वास्तव में इसे * पूरी तरह से * निरंतर होना चाहते हैं, जो असंभव है। – Veedrac

उत्तर

2

आपकी कक्षा कॉन्स्टेंट को एक नई शैली पायथन कक्षा होने के लिए ऑब्जेक्ट से उत्तराधिकारी होना चाहिए।

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

आपके उदाहरण में कॉन्स्टेंट वर्णनकर्ता है और ग्रह में एक विशेषता है जो कॉन्स्टेंट का एक उदाहरण है। जब आपको प्लैनेट क्लास की विशेषता जी (आपके उदाहरण में self.G) मिलती है, तो आपको वास्तव में क्या मिलता है जो वर्णनकर्ता की __get__ विधि द्वारा वापस किया जाता है, यह मान है।

ध्यान दें कि __get__ केवल तभी लगाया जाता है जब वर्णनकर्ता उदाहरण किसी अन्य वर्ग विशेषता द्वारा उपयोग किया जाता है।

तो, इस तरह वर्ग को परिभाषित:

class Constant(object): 
    def __init__(self, value): 
     self.value = value 
    def __get__(self, *args): 
     return self.value 
    def __repr__(self): 
     return '%s(%r)' % (self.__class__.__name__, self.value) 

तो इस छोटे से उदाहरण:

c = Constant(3.14) 
print c 

class Test: 
    c = Constant(3.14) 

t = Test() 
print t.c 

प्रिंट होगा:

Constant(3.14) 
3.14 

देखें जब लगातार उदाहरण सीधे मुद्रित किया जाता है कि , विधि __repr__ कहा जाएगा, लेकिन जब किसी अन्य वर्ग विशेषता के रूप में मुद्रित किया जाता है, तो __get__ का उपयोग किया जाएगा।

आप this great article पर वर्णनकर्ताओं पर और अधिक पढ़ सकते हैं।

+0

जो मैंने परीक्षण किया है उससे केवल तभी काम करता है जब यह क्लास वैरिएबल है और इंस्टेंस वैरिएबल नहीं है। यदि मैं 'c = Constant' को' __init__' में 'self.c = Constant (...)' के माध्यम से ले जाता हूं तो मुझे '__repr__' आउटपुट मिलता है। और यह अभी भी लिखने योग्य है जो निरंतर के लिए ठीक है क्योंकि मैं सभी सीएपीएस के साथ नाम कर सकता हूं। आदर्श रूप से, मैं कक्षा के भीतर से एक उदाहरण परिवर्तनीय लेखन-सक्षम बनाने का तरीका ढूंढने की उम्मीद कर रहा हूं लेकिन '__main__' स्क्रिप्ट के बाहर नहीं। मेरे पास PHP में कुछ था जिसने यह काफी अच्छा किया लेकिन अब तक जो मैंने पढ़ा है, वह पाइथन में संभव नहीं है। वर्ग विशेषता हमेशा ओवरराइट के लिए उपलब्ध प्रतीत होती है। धन्यवाद –

0

अच्छा, value आपके class Constant का एक ज्ञापन है; ताकि आप making it private कोशिश कर सकते हैं:

class Constant: 
    def __init__(self, value): 
    # This actually transforms the variable to _Constant__value, 
    # but also hides it from outer scope 
    self.__value = value 
    def __get__(self, *args): 
    # Altough the member is theorically renamed as _Constant__value, 
    # it is completely accesible from inside the class as __value 
    reurn self.__value 
    def __repr__(self): 
    return '%s(%r)' % (self.__class__.__name__, self.__value) 

एक और दृष्टिकोण this recipe निम्नलिखित जा सकता है।

उन्हें आज़माएं और मुझे अभी दो। आशा है कि मैं आपकी मदद करूंगा!

+0

मैंने अभी तक नुस्खा की कोशिश नहीं की है लेकिन आपके द्वारा प्रदान किया गया कोड मेरे लिए काम नहीं करता है क्योंकि यह स्वयं का उदाहरण है। मैं सीधे मूल्य पर नहीं पहुंच सका। मुझे संदेह है कि यह @baxeico ने कहा है कि यह एक कक्षा के भीतर एक वर्णक बनना चाहिए। Thx –

+0

नुस्खा काम करने के लिए प्रतीत होता है। हालांकि, यह एक फ़ाइल में रहना चाहिए और आयात किया जाना चाहिए। यह एक सिंगलटन भी प्रतीत होता है। इसे कक्षा (केवल कक्षा परिभाषा के नीचे) के भीतर आयात करना उस वर्ग के नामस्थान तक सीमित नहीं है। न ही आयात लाइन को '__init__' में डालता है। यदि आप इन सीमाओं के साथ रह सकते हैं तो नुस्खा काफी अच्छी तरह से काम करता है। –

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