]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-72902: Speedup Fraction.from_decimal/float in typical cases (GH-133251)
authorSergey B Kirpichev <skirpichev@gmail.com>
Mon, 25 May 2026 07:04:56 +0000 (10:04 +0300)
committerGitHub <noreply@github.com>
Mon, 25 May 2026 07:04:56 +0000 (10:04 +0300)
Lib/fractions.py
Misc/NEWS.d/next/Library/2025-05-01-16-44-16.gh-issue-72902.19qwJW.rst [new file with mode: 0644]

index c1b12e7a1c091c698b7398986ca1f3c95eb69204..84e844cdd697687304340267e93a5ea10997794f 100644 (file)
@@ -339,24 +339,24 @@ class Fraction(numbers.Rational):
         Beware that Fraction.from_float(0.3) != Fraction(3, 10).
 
         """
+        if isinstance(f, float):
+            return cls._from_coprime_ints(*f.as_integer_ratio())
         if isinstance(f, numbers.Integral):
             return cls(f)
-        elif not isinstance(f, float):
-            raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
-                            (cls.__name__, f, type(f).__name__))
-        return cls._from_coprime_ints(*f.as_integer_ratio())
+        raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
+                        (cls.__name__, f, type(f).__name__))
 
     @classmethod
     def from_decimal(cls, dec):
         """Converts a finite Decimal instance to a rational number, exactly."""
         from decimal import Decimal
+        if isinstance(dec, Decimal):
+            return cls._from_coprime_ints(*dec.as_integer_ratio())
         if isinstance(dec, numbers.Integral):
-            dec = Decimal(int(dec))
-        elif not isinstance(dec, Decimal):
-            raise TypeError(
-                "%s.from_decimal() only takes Decimals, not %r (%s)" %
-                (cls.__name__, dec, type(dec).__name__))
-        return cls._from_coprime_ints(*dec.as_integer_ratio())
+            dec = int(dec)
+            return cls._from_coprime_ints(*dec.as_integer_ratio())
+        raise TypeError("%s.from_decimal() only takes Decimals, not %r (%s)" %
+                        (cls.__name__, dec, type(dec).__name__))
 
     @classmethod
     def _from_coprime_ints(cls, numerator, denominator, /):
diff --git a/Misc/NEWS.d/next/Library/2025-05-01-16-44-16.gh-issue-72902.19qwJW.rst b/Misc/NEWS.d/next/Library/2025-05-01-16-44-16.gh-issue-72902.19qwJW.rst
new file mode 100644 (file)
index 0000000..2b7d8e4
--- /dev/null
@@ -0,0 +1,3 @@
+Optimize (~x1.4 speedup) :meth:`fractions.Fraction.from_decimal` and
+:meth:`fractions.Fraction.from_float` for :class:`~decimal.Decimal` and
+:class:`float` inputs, respectively.  Patch by Sergey B Kirpichev.