मैं इसे पायथन 3.4 और 3.7 दोनों पर पुन: पेश करने में कामयाब रहा।

विचार करना:

class Comparable:
    def _key(self):
        raise NotImplementedError

    def __hash__(self):
        return hash(self._key())

    def __eq__(self, other):
        ...

    def __lt__(self, other):
        ...


class A(Comparable): pass

class B(A):
    def __str__(self):
        return "d"

    def __eq__(self, other):
        return isinstance(self, type(other))

    def _key(self):
        return str(self),

b = B()

स्पष्ट रूप से कोई उम्मीद करेगा कि b.__hash__ को यहां परिभाषित किया जाएगा, क्योंकि इसे Comparable के तहत परिभाषित किया गया है, जो B का एक उपवर्ग है।

देखो और देखो, यह परिभाषित है, लेकिन None का मूल्यांकन करता है। क्या दिया?

>> b
<__main__.B object at 0x00000183C9734978>
>> '__hash__' in dir(b)
True
>> b.__hash__

>> b.__hash__ is None
True
>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class '__main__.Comparable'>, <class 'object'>)
>> isinstance(b, Comparable)
True

__init__ को Comparable और A में super().__init__() के रूप में लागू करने पर वही व्यवहार पुन: उत्पन्न होता है।

8
DeepSpace 28 नवम्बर 2018, 14:59

1 उत्तर

सबसे बढ़िया उत्तर

इसे दस्तावेज़ में मिला:

एक वर्ग जो __eq__() को ओवरराइड करता है और __hash__() को परिभाषित नहीं करता है, उसका __hash__() परोक्ष रूप से कोई नहीं पर सेट होगा।

तथा

यदि कोई वर्ग जो __eq__() को ओवरराइड करता है, उसे मूल वर्ग से __hash__() के कार्यान्वयन को बनाए रखने की आवश्यकता है, तो दुभाषिया को __hash__ = <ParentClass>.__hash__ सेट करके यह स्पष्ट रूप से बताया जाना चाहिए।

टिकट से 1549:

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

(गुइडो वैन रोसुम)

17
kabanus 28 नवम्बर 2018, 15:13