New submission from Ethan Furman <et...@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 <rep...@bugs.python.org>
<http://bugs.python.org/issue14617>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to