From f3cb68f2e4c3e0c405460f9bb881f5c1db70f535 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 15 Aug 2019 20:58:26 -0700 Subject: [PATCH] bpo-37863: Optimize Fraction.__hash__() (#15298) --- Lib/fractions.py | 24 ++++++++----------- .../2019-08-14-20-46-39.bpo-37863.CkXqgX.rst | 1 + 2 files changed, 11 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst diff --git a/Lib/fractions.py b/Lib/fractions.py index e774d58e403..c922c38e244 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -556,23 +556,19 @@ class Fraction(numbers.Rational): def __hash__(self): """hash(self)""" - # XXX since this method is expensive, consider caching the result + # 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'). - # 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: + 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 index 00000000000..90df6e9cb65 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst @@ -0,0 +1 @@ +Optimizations for Fraction.__hash__ suggested by Tim Peters.