]> granicus.if.org Git - python/commitdiff
Merge #14617: clarify discussion of interrelationship of __eq__ and __hash__.
authorR David Murray <rdmurray@bitdance.com>
Tue, 11 Sep 2012 17:02:13 +0000 (13:02 -0400)
committerR David Murray <rdmurray@bitdance.com>
Tue, 11 Sep 2012 17:02:13 +0000 (13:02 -0400)
1  2 
Doc/reference/datamodel.rst

index b2ce4ffe73fe74d94761da2cd36a84fd1204098b,2ddb852468e32c8a1494416a47a5c5feedd6a3a3..1c8c190fc87e52803eb7d62db8847fa96d117f54
@@@ -1266,49 -1250,29 +1266,49 @@@ Basic customizatio
     immutable (if the object's hash value changes, it will be in the wrong hash
     bucket).
  
 -
     User-defined classes have :meth:`__eq__` and :meth:`__hash__` methods
     by default; with them, all objects compare unequal (except with themselves)
 -   and ``x.__hash__()`` returns ``id(x)``.
 +   and ``x.__hash__()`` returns an appropriate value such that ``x == y``
 +   implies both that ``x is y`` and ``hash(x) == hash(y)``.
  
-    Classes which inherit a :meth:`__hash__` method from a parent class but
-    change the meaning of :meth:`__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 :exc:`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 :meth:`__hash__` to explicitly raise :exc:`TypeError`).
+    A class that overrides :meth:`__eq__` and does not define :meth:`__hash__`
+    will have its :meth:`__hash__` implicitly set to ``None``.  When the
+    :meth:`__hash__` method of a class is ``None``, instances of the class will
+    raise an appropriate :exc:`TypeError` when a program attempts to retrieve
+    their hash value, and will also be correctly identified as unhashable when
+    checking ``isinstance(obj, collections.Hashable``).
  
     If a class that overrides :meth:`__eq__` needs to retain the implementation
     of :meth:`__hash__` from a parent class, the interpreter must be told this
-    explicitly by setting ``__hash__ = <ParentClass>.__hash__``. Otherwise the
-    inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__`
-    had been explicitly set to :const:`None`.
+    explicitly by setting ``__hash__ = <ParentClass>.__hash__``.
+    If a class that does not override :meth:`__eq__` wishes to suppress hash
+    support, it should include ``__hash__ = None`` in the class definition.
+    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.
  
 -   See also the :option:`-R` command-line option.
 +
 +   .. note::
 +
 +      By default, the :meth:`__hash__` values of str, bytes and datetime
 +      objects are "salted" with an unpredictable random value.  Although they
 +      remain constant within an individual Python process, they are not
 +      predictable between repeated invocations of Python.
 +
 +      This is intended to provide protection against a denial-of-service caused
 +      by carefully-chosen inputs that exploit the worst case performance of a
 +      dict insertion, O(n^2) complexity.  See
 +      http://www.ocert.org/advisories/ocert-2011-003.html for details.
 +
 +      Changing hash values affects the iteration order of dicts, sets and
 +      other mappings.  Python has never made guarantees about this ordering
 +      (and it typically varies between 32-bit and 64-bit builds).
 +
 +      See also :envvar:`PYTHONHASHSEED`.
 +
 +   .. versionchanged:: 3.3
 +      Hash randomization is enabled by default.
  
  
  .. method:: object.__bool__(self)