继承-__hash__在子类中设置为None

时间:2018-11-28 11:59:22

标签: python inheritance

我设法在Python 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是其子类。

Lo并已定义,但计算结果为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__super().__init__()中将Comparable实现为A,则会再现相同的行为。

1 个答案:

答案 0 :(得分:5)

the docs中找到它:

  

覆盖\并且未定义__eq__()的类将其__hash__()隐式设置为None。

  

如果覆盖__hash__()的类需要保留父类__eq__()的实现,则必须通过设置__hash__()

明确地告诉解释器。

从票证1549

  

这是有意完成的-如果您定义的比较没有   定义哈希,则默认哈希将与您的比较不匹配,并且   当用作字典键时,您的对象将无法正常工作。

(Guido van Rossum)