Types that define `__eq__` are unhashable?

后端 未结 4 1649
青春惊慌失措
青春惊慌失措 2020-11-27 05:05

I had a strange bug when porting a feature to the Python 3.1 fork of my program. I narrowed it down to the following hypothesis:

In contrast to Python 2.x, in Python

相关标签:
4条回答
  • 2020-11-27 05:32

    This paragraph from http://docs.python.org/3.1/reference/datamodel.html#object.hash

    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__. Otherwise the inheritance of __hash__() will be blocked, just as if __hash__ had been explicitly set to None.

    0 讨论(0)
  • 2020-11-27 05:43

    I'm no python expert, but wouldn't it make sense that, when you define a eq-method, you also have to define a hash-method as well (which calculates the hash value for an object) Otherwise, the hashing mechanism wouldn't know if it hit the same object, or a different object with just the same hash-value. Actually, it's the other way around, it'd probably end up computing different hash values for objects considered equal by your __eq__ method.

    I have no idea what that hash function is called though, __hash__ perhaps? :)

    0 讨论(0)
  • 2020-11-27 05:51

    Yes, if you define __eq__, the default __hash__ (namely, hashing the address of the object in memory) goes away. This is important because hashing needs to be consistent with equality: equal objects need to hash the same.

    The solution is simple: just define __hash__ along with defining __eq__.

    0 讨论(0)
  • 2020-11-27 05:57

    Check the Python 3 manual on object.__hash__:

    If a class does not define an __eq__() method it should not define a __hash__() operation either; if it defines __eq__() but not __hash__(), its instances will not be usable as items in hashable collections.

    Emphasis is mine.

    If you want to be lazy, it sounds like you can just define __hash__(self) to return id(self):

    User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns id(x).

    0 讨论(0)
提交回复
热议问题