Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
458 views
in Technique[技术] by (71.8m points)

python - Inheritance - __hash__ sets to None in a subclass

I managed to reproduce this on both Python 3.4 and 3.7.

Consider:

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()

Clearly one would expect b.__hash__ to be defined here, since it is defined under Comparable which B is a subclass of.

Lo and behold, it is defined, but evaluates to None. What gives?

>> 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

The same behavior is reproduced if implementing __init__ as super().__init__() in Comparable and A.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Found it in the docs:

A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None.

and

If a class that overrides __eq__() needs to retain the implementation of __hash__() from a parent class, the interpreter must be told this explicitly by setting __hash__ = <ParentClass>.__hash__

From ticket 1549:

This was done intentionally -- if you define a comparison without defining a hash, the default hash will not match your comparison, and your objects will misbehave when used as dictionary keys.

(Guido van Rossum)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...