]> granicus.if.org Git - python/commitdiff
bpo-37863: Optimize Fraction.__hash__() (#15298)
authorRaymond Hettinger <rhettinger@users.noreply.github.com>
Fri, 16 Aug 2019 03:58:26 +0000 (20:58 -0700)
committerGitHub <noreply@github.com>
Fri, 16 Aug 2019 03:58:26 +0000 (20:58 -0700)
Lib/fractions.py
Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst [new file with mode: 0644]

index e774d58e403539bfee8c999031388451738865d2..c922c38e244116f6c0abd49162625dfdc1630a70 100644 (file)
@@ -556,23 +556,19 @@ class Fraction(numbers.Rational):
     def __hash__(self):
         """hash(self)"""
 
-        # XXX since this method is expensive, consider caching the result
-
-        # In order to make sure that the hash of a Fraction agrees
-        # with the hash of a numerically equal integer, float or
-        # Decimal instance, we follow the rules for numeric hashes
-        # outlined in the documentation.  (See library docs, 'Built-in
-        # Types').
-
-        # dinv is the inverse of self._denominator modulo the prime
-        # _PyHASH_MODULUS, or 0 if self._denominator is divisible by
-        # _PyHASH_MODULUS.
-        dinv = pow(self._denominator, _PyHASH_MODULUS - 2, _PyHASH_MODULUS)
-        if not dinv:
+        # To make sure that the hash of a Fraction agrees with the hash
+        # of a numerically equal integer, float or Decimal instance, we
+        # follow the rules for numeric hashes outlined in the
+        # documentation.  (See library docs, 'Built-in Types').
+
+        try:
+            dinv = pow(self._denominator, -1, _PyHASH_MODULUS)
+        except ValueError:
+            # ValueError means there is no modular inverse
             hash_ = _PyHASH_INF
         else:
-            hash_ = abs(self._numerator) * dinv % _PyHASH_MODULUS
-        result = hash_ if self >= 0 else -hash_
+            hash_ = hash(abs(self._numerator)) * dinv % _PyHASH_MODULUS
+        result = hash_ if self._numerator >= 0 else -hash_
         return -2 if result == -1 else result
 
     def __eq__(a, b):
diff --git a/Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst b/Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst
new file mode 100644 (file)
index 0000000..90df6e9
--- /dev/null
@@ -0,0 +1 @@
+Optimizations for Fraction.__hash__ suggested by Tim Peters.