gh-121797: Add class method Fraction.from_number() (GH-121800)

It is an alternative constructor which only accepts a single numeric argument.
Unlike to Fraction.from_float() and Fraction.from_decimal() it accepts any
real numbers supported by the standard constructor (int, float, Decimal,
Rational numbers, objects with as_integer_ratio()).
Unlike to the standard constructor, it does not accept strings.
This commit is contained in:
Serhiy Storchaka 2024-10-14 10:54:59 +03:00 committed by GitHub
parent 66b3922b97
commit b52c7306ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 82 additions and 8 deletions

View file

@ -279,7 +279,8 @@ class Fraction(numbers.Rational):
numerator = -numerator
else:
raise TypeError("argument should be a string or a number")
raise TypeError("argument should be a string or a Rational "
"instance or have the as_integer_ratio() method")
elif type(numerator) is int is type(denominator):
pass # *very* normal case
@ -305,6 +306,28 @@ class Fraction(numbers.Rational):
self._denominator = denominator
return self
@classmethod
def from_number(cls, number):
"""Converts a finite real number to a rational number, exactly.
Beware that Fraction.from_number(0.3) != Fraction(3, 10).
"""
if type(number) is int:
return cls._from_coprime_ints(number, 1)
elif isinstance(number, numbers.Rational):
return cls._from_coprime_ints(number.numerator, number.denominator)
elif (isinstance(number, float) or
(not isinstance(number, type) and
hasattr(number, 'as_integer_ratio'))):
return cls._from_coprime_ints(*number.as_integer_ratio())
else:
raise TypeError("argument should be a Rational instance or "
"have the as_integer_ratio() method")
@classmethod
def from_float(cls, f):
"""Converts a finite float to a rational number, exactly.