classification
Title: Hashable doesn't check for __eq__
Type: Stage: resolved
Components: Documentation Versions:
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: docs@python, max, rhettinger
Priority: normal Keywords:

Created on 2017-04-09 16:23 by max, last changed 2017-04-09 18:40 by rhettinger. This issue is now closed.

Messages (3)
msg291382 - (view) Author: Max (max) * Date: 2017-04-09 16:23
I think collections.abc.Hashable.__subclasshook__ should check __eq__ method in addition to __hash__ method. This helps detect classes that are unhashable due to:

to __eq__ = None

Of course, it still cannot detect:

def __eq__: return NotImplemented

but it's better than nothing.

In addition, it's probably worth documenting that explicitly inheriting from Hashable has (correct but unexpected) effect of *suppressing* hashability that was already present:

from collections.abc import Hashable
class X: pass
assert issubclass(X, Hashable)
x = X()

class X(Hashable): pass
assert issubclass(X, Hashable)
x = X() # Can't instantiate abstract class X with abstract methods
msg291383 - (view) Author: Max (max) * Date: 2017-04-09 16:25
Sorry, this should be just a documentation issue.

I just realized that __eq__ = None isn't correct anyway, so instead we should just document that Hashable cannot check for __eq__ and that explicitly deriving from Hashable suppresses hashability.
msg291385 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-04-09 18:40
> # Can't instantiate abstract class X with abstract methods

Sorry, this is how ABCs are supposed to work.  They use @abstractmethod to specify requirements that a subclass if required to implement.  The ABC metaclass then enforces that requirement, preventing instantiation unless those requirements are met.  If not met, they give a reasonably clear error message, "TypeError: Can't instantiate abstract class A with abstract methods __hash__".
History
Date User Action Args
2017-04-09 18:40:47rhettingersetstatus: open -> closed

assignee: docs@python -> rhettinger

nosy: + rhettinger
messages: + msg291385
resolution: not a bug
stage: resolved
2017-04-09 16:25:43maxsetmessages: + msg291383
components: - Interpreter Core
2017-04-09 16:23:03maxcreate