[issue14617] confusing docs with regard to __hash__

New submission from Ethan Furman <ethan@stoneleaf.us>:
From http://docs.python.org/py3k/reference/datamodel.html#object.__hash__
Classes which inherit a __hash__() method from a parent class but change the meaning of __eq__() such that the hash value returned is no longer appropriate (e.g. by switching to a value-based concept of equality instead of the default identity based equality) can explicitly flag themselves as being unhashable by setting __hash__ = None in the class definition. Doing so means that not only will instances of the class raise an appropriate TypeError when a program attempts to retrieve their hash value, but they will also be correctly identified as unhashable when checking isinstance(obj, collections.Hashable) (unlike classes which define their own __hash__() to explicitly raise TypeError). 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. ----------------------------------------------------------------------- The first paragraph says the user has to change __hash__ if it's different because of changes to __eq__, the second paragraph says __hash__ is automatically removed if __eq__ is changed; the second paragraph reflects reality. Proposed change: ----------------------------------------------------------------------- Classes which change the meaning of __eq__() (thus losing automatic delegation to the parent class' __hash__) can explicitly flag themselves as being unhashable by setting __hash__ = None in the class definition (which is otherwise done implicity). Having __hash__ set to None, either explicitly or implicitly, means that not only will instances of the class raise an appropriate TypeError when a program attempts to retrieve their hash value, but they will also be correctly identified as unhashable when checking isinstance(obj, collections.Hashable) (unlike classes which define their own __hash__() to explicitly raise TypeError). 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__. ----------------------------------------------------------------------- Patch attached. ---------- assignee: docs@python components: Documentation, Interpreter Core files: __hash__.diff keywords: patch messages: 158644 nosy: docs@python, stoneleaf priority: normal severity: normal status: open title: confusing docs with regard to __hash__ type: behavior versions: Python 3.1, Python 3.2, Python 3.3 Added file: http://bugs.python.org/file25261/__hash__.diff _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Changes by Éric Araujo <merwok@netwok.org>: ---------- versions: +Python 2.7 -Python 3.1 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman <ethan@stoneleaf.us> added the comment: Éric Araujo wrote:
Changes by Éric Araujo <merwok@netwok.org>:
---------- versions: +Python 2.7 -Python 3.1
The docs for 2.7 are correct, as __hash__ is not automatically suppressed in that version. -- ~Ethan~ ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Éric Araujo <merwok@netwok.org> added the comment: Some of the sentence phrasing still sounds a bit awkward to me (“[...], means that not only will instances” for example, and I would also remove the parens at the end), but globally I think this is an improvement. ---------- nosy: +eric.araujo _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Changes by Éric Araujo <merwok@netwok.org>: ---------- versions: -Python 2.7 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman <ethan@stoneleaf.us> added the comment: More re-writing... ---------- Added file: http://bugs.python.org/file25264/__hash__2.diff _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Changes by Arfrever Frehtes Taifersar Arahesis <Arfrever.FTA@GMail.Com>: ---------- nosy: +Arfrever _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman <ethan@stoneleaf.us> added the comment: Are the changes good? Can they be commited? ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Changes by Chris Rebert <pybugs@rebertia.com>: ---------- nosy: +cvrebert _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman <ethan@stoneleaf.us> added the comment: Newest changes uploaded. ---------- Added file: http://bugs.python.org/file25707/__hash__3.diff _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman added the comment: Any problems with the current doc patch? If not, can it be applied before RC1? ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Changes by Antoine Pitrou <pitrou@free.fr>: ---------- nosy: +ncoghlan _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman added the comment: RC2 has just been released. Any chance of this getting in to the final release? Nobobdy has pointed out any problems with the last update... ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Roundup Robot added the comment: New changeset 957e1eef3296 by R David Murray in branch '3.2': #14617: clarify discussion of interrelationship of __eq__ and __hash__. http://hg.python.org/cpython/rev/957e1eef3296 New changeset c8d60d0c736b by R David Murray in branch 'default': Merge #14617: clarify discussion of interrelationship of __eq__ and __hash__. http://hg.python.org/cpython/rev/c8d60d0c736b ---------- nosy: +python-dev _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

R. David Murray added the comment: I rewrote the section a bit differently than you did in your patch...if you think my changes are not an improvement please let me know. ---------- nosy: +r.david.murray resolution: -> fixed stage: -> committed/rejected status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman added the comment: R. David Murray wrote:
I rewrote the section a bit differently than you did in your patch...if you think my changes are not an improvement please let me know.
This line is incorrect: A class which defines its own :meth:`__hash__` that explicitly raises a :exc:`TypeError` would be incorrectly identified as hashable by an ``isinstance(obj, collections.Hashable)`` call. It should be "would not be correctly identified as hashable". Otherwise, looks great. ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Ethan Furman added the comment: Ethan Furman wrote:
Ethan Furman added the comment:
R. David Murray wrote:
I rewrote the section a bit differently than you did in your patch...if you think my changes are not an improvement please let me know.
This line is incorrect:
A class which defines its own :meth:`__hash__` that explicitly raises a :exc:`TypeError` would be incorrectly identified as hashable by an ``isinstance(obj, collections.Hashable)`` call.
It should be "would not be correctly identified as hashable".
Otherwise, looks great.
Argh. Nevermind! It all looks good. :) ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________

Raymond Hettinger added the comment: This can wait until after the release. We will have periodic point releases where further doc updates can go in. ---------- nosy: +rhettinger _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue14617> _______________________________________
participants (8)
-
Antoine Pitrou
-
Arfrever Frehtes Taifersar Arahesis
-
Chris Rebert
-
Ethan Furman
-
R. David Murray
-
Raymond Hettinger
-
Roundup Robot
-
Éric Araujo