2010-09-02 7 views
39

मान लीजिए मैं एक namedtuple इस तरह है:नामांकित उप-वर्ग के लिए अतिरिक्त प्रारंभिकरण कैसे प्रदान करें?

EdgeBase = namedtuple("EdgeBase", "left, right") 

मैं इस के लिए एक कस्टम हैश समारोह लागू करना चाहते हैं, तो मैं निम्नलिखित उपवर्ग बनाएँ:

class Edge(EdgeBase): 
    def __hash__(self): 
     return hash(self.left) * hash(self.right) 

के बाद वस्तु अपरिवर्तनीय है, मैं चाहते हैश मूल्य केवल एक बार की गणना करने के, तो मैं ऐसा करते हैं:

class Edge(EdgeBase): 
    def __init__(self, left, right): 
     self._hash = hash(self.left) * hash(self.right) 

    def __hash__(self): 
     return self._hash 

यह काम कर रहा है, लेकिन मैं वास्तव में के बारे में यकीन नहीं है पाइथन में विशेष रूप से tuples के साथ ubclassing और प्रारंभिकरण। क्या इस समाधान के लिए कोई नुकसान है? क्या ऐसा करने का एक अनुशंसित तरीका है? यह ठीक है? अग्रिम में धन्यवाद।

+1

टेस्ट से पता चला है कि हैश मान को कैश करने के लायक नहीं है, देखें [समस्या # 9685] (https://mail.python.org/pipermail/python-bugs-list/2013-January/192363.html) –

उत्तर

44

2017 के लिए संपादित करें:turns out namedtuple isn't a great ideaattrs आधुनिक विकल्प है।

class Edge(EdgeBase): 
    def __new__(cls, left, right): 
     self = super(Edge, cls).__new__(cls, left, right) 
     self._hash = hash(self.left) * hash(self.right) 
     return self 

    def __hash__(self): 
     return self._hash 

__new__ क्या तुम यहाँ कॉल करने के लिए क्योंकि tuples अपरिवर्तनीय हैं चाहते हैं। अपरिवर्तनीय वस्तुएं __new__ में बनाई गई हैं और फिर __init__ में डेटा के साथ आबादी के बजाय उपयोगकर्ता को लौट आईं।

cls दो बार ऐतिहासिक/अजीब कारणों परोक्ष एक staticmethod के लिए, __new__ पर super कॉल करने के लिए पारित किया जा सकता है क्योंकि __new__ है।

+3

मुझे इसे अपने समाधान के लिए क्यों पसंद करना चाहिए (यह एक सनकी सवाल नहीं है, मैं वास्तव में समझना चाहता हूं कि क्या कोई महत्वपूर्ण अंतर है)? –

+9

आपका समाधान 'सुपर' का उपयोग नहीं करता है, और इसलिए किसी भी प्रकार की एकाधिक विरासत स्थिति में तोड़ देगा। इससे कोई फर्क नहीं पड़ता कि * आप * एमआई का उपयोग नहीं करते हैं; अगर कोई और करता है, तो उनका कोड बहुत ही टूट जाएगा। हर जगह 'सुपर' का उपयोग करके इस मुद्दे से बचना मुश्किल नहीं है। – habnabit

+5

कक्षा में '__slots__ =()' जोड़ने के लिए भी फायदेमंद है। अन्यथा '__dict__' बनाया जाएगा, 'नामित' की स्मृति दक्षता को अस्वीकार कर दिया जाएगा। – WGH

3

प्रश्न में कोड को __init__ में एक सुपर कॉल से लाभ हो सकता है यदि यह कभी भी एकाधिक विरासत स्थिति में उप-वर्गीकृत हो जाता है, लेकिन अन्यथा सही है।

class Edge(EdgeBase): 
    def __init__(self, left, right): 
     super(Edge, self).__init__(a, b) 
     self._hash = hash(self.left) * hash(self.right) 

    def __hash__(self): 
     return self._hash 

tuples केवल पढ़ने के लिए केवल अपने उपवर्गों की टपल भागों केवल पढ़ने के लिए कर रहे हैं, अन्य संपत्तियों के सामान्य जो क्या काम है कि क्या यह __init__ या __new__ में किया है की परवाह किए बिना _hash करने की अनुमति देता है के रूप में लिखा जा सकता है कर रहे हैं। आप subclass को __slots__() में सेट करके पूरी तरह से पढ़ा जा सकता है, जिसमें स्मृति को सहेजने का अतिरिक्त लाभ है, लेकिन फिर आप _hash को असाइन करने में सक्षम नहीं होंगे।

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