diff --git a/Lib/decimal.py b/Lib/decimal.py --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -547,7 +547,7 @@ class Decimal(object): """Floating point class for decimal arithmetic.""" - __slots__ = ('_exp','_int','_sign', '_is_special') + __slots__ = ('_exp','_int','_sign', '_is_special', '_hash') # Generally, the value of the Decimal instance is given by # (-1)**_sign * _int * 10**_exp # Special values are signified by _is_special == True @@ -577,6 +577,7 @@ # digits. self = object.__new__(cls) + self._hash = -1 # From a string # REs insist on real strings, so we can too. @@ -988,6 +989,7 @@ # agrees with the hash of a numerically equal integer, float # or Fraction, we follow the rules for numeric hashes outlined # in the documentation. (See library docs, 'Built-in Types'). + if self._is_special: if self.is_snan(): raise TypeError('Cannot hash a signaling NaN value.') @@ -998,6 +1000,8 @@ return -_PyHASH_INF else: return _PyHASH_INF + if self._hash != -1: + return self._hash if self._exp >= 0: exp_hash = pow(10, self._exp, _PyHASH_MODULUS) @@ -1005,7 +1009,9 @@ exp_hash = pow(_PyHASH_10INV, -self._exp, _PyHASH_MODULUS) hash_ = int(self._int) * exp_hash % _PyHASH_MODULUS ans = hash_ if self >= 0 else -hash_ - return -2 if ans == -1 else ans + ans = -2 if ans == -1 else ans + self._hash = ans + return ans def as_tuple(self): """Represents the number as a triple tuple.