diff --git a/Lib/fractions.py b/Lib/fractions.py index c1b12e7a1c091c..84e844cdd69768 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -339,24 +339,24 @@ def from_float(cls, f): 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 index 00000000000000..2b7d8e44840894 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-01-16-44-16.gh-issue-72902.19qwJW.rst @@ -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.