जॉन मिलिकिन ने इसके समान एक समाधान प्रस्तावित किया:
class A(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
def __eq__(self, othr):
return (isinstance(othr, type(self))
and (self._a, self._b, self._c) ==
(othr._a, othr._b, othr._c))
def __hash__(self):
return hash((self._a, self._b, self._c))
इस समाधान के साथ समस्या यह है कि है hash(A(a, b, c)) == hash((a, b, c))
। दूसरे शब्दों में, हैश अपने प्रमुख सदस्यों के टपल से टकराता है। शायद यह बहुत बार अभ्यास में नहीं होता है?
अद्यतन: पायथन डॉक्स अब ऊपर के उदाहरण के रूप में एक टपल का उपयोग करने की सलाह देते हैं। ध्यान दें कि दस्तावेज़ बताता है
केवल आवश्यक संपत्ति यह है कि जो वस्तुएं समान तुलना करती हैं उनका समान हैश मूल्य होता है
ध्यान दें कि विपरीत सच नहीं है। जो वस्तुएं समान की तुलना नहीं करती हैं, उनका मूल्य समान हैश हो सकता है। इस तरह की हैश टक्कर एक वस्तु को दूसरे की जगह लेने का कारण नहीं बनेगी, जब एक प्रमुख कुंजी या सेट तत्व के रूप में उपयोग किया जाता है जब तक कि वस्तुओं की तुलना न हो ।
खराब / खराब समाधान
पर पायथन प्रलेखन__hash__
XOR की तरह कुछ का उपयोग कर उप घटकों के हैश गठबंधन करने के लिए पता चलता है , जो हमें इस देता है:
class B(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
def __eq__(self, othr):
if isinstance(othr, type(self)):
return ((self._a, self._b, self._c) ==
(othr._a, othr._b, othr._c))
return NotImplemented
def __hash__(self):
return (hash(self._a) ^ hash(self._b) ^ hash(self._c) ^
hash((self._a, self._b, self._c)))
अपडेट: ब्लैंकथन बताते हैं कि, a, b और c के क्रम को बदलने से समस्या हो सकती है। मैंने ^ hash((self._a, self._b, self._c))
हैश किए जाने वाले मूल्यों के क्रम को पकड़ने के लिए एक अतिरिक्त जोड़ा । इस अंतिम ^ hash(...)
मान जा रहा है संयुक्त पुन: व्यवस्थित नहीं किया जा सकता है, तो हटाया जा सकता है (उदाहरण के लिए, वे विभिन्न प्रकार के और इसलिए का मूल्य है, तो _a
को सौंपा जा कभी नहीं होगा _b
या _c
, आदि)।
__key
समारोह में फैक्टरिंग से मामूली ओवरहेड के अलावा , यह किसी भी हैश के रूप में तेजी से हो सकता है। निश्चित रूप से, यदि विशेषताओं को पूर्णांक के रूप में जाना जाता है, और उनमें से बहुत सारे नहीं हैं, तो मुझे लगता है कि आप संभावित रूप से कुछ होम-रोल्ड हैश के साथ थोड़ा तेज दौड़ सकते हैं , लेकिन यह संभवतः वितरित नहीं होगा।hash((self.attr_a, self.attr_b, self.attr_c))
आश्चर्यजनक रूप से तेज़ (और सही ) होने जा रहा है , क्योंकि छोटेtuple
एस का निर्माण विशेष रूप से अनुकूलित है, और यह सी बिल्डरों में हैश को प्राप्त करने और संयोजन करने के काम को आगे बढ़ाता है, जो आमतौर पर पायथन स्तर के कोड की तुलना में तेज है।