Merged revisions 71832 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r71832 | mark.dickinson | 2009-04-24 14:56:07 +0100 (Fri, 24 Apr 2009) | 3 lines

  Issue #5812: The two-argument form of the Fraction constructor
  now accepts arbitrary Rational instances.
........
This commit is contained in:
Mark Dickinson 2009-04-24 14:06:19 +00:00
parent f21bd3cc2f
commit d4d95f8eac
3 changed files with 32 additions and 13 deletions

View file

@ -54,7 +54,7 @@ class Fraction(numbers.Rational):
__slots__ = ('_numerator', '_denominator') __slots__ = ('_numerator', '_denominator')
# We're immutable, so use __new__ not __init__ # We're immutable, so use __new__ not __init__
def __new__(cls, numerator=0, denominator=1): def __new__(cls, numerator=0, denominator=None):
"""Constructs a Rational. """Constructs a Rational.
Takes a string like '3/2' or '1.5', another Rational, or a Takes a string like '3/2' or '1.5', another Rational, or a
@ -63,8 +63,13 @@ class Fraction(numbers.Rational):
""" """
self = super(Fraction, cls).__new__(cls) self = super(Fraction, cls).__new__(cls)
if not isinstance(numerator, int) and denominator == 1: if denominator is None:
if isinstance(numerator, str): if isinstance(numerator, numbers.Rational):
self._numerator = numerator.numerator
self._denominator = numerator.denominator
return self
elif isinstance(numerator, str):
# Handle construction from strings. # Handle construction from strings.
m = _RATIONAL_FORMAT.match(numerator) m = _RATIONAL_FORMAT.match(numerator)
if m is None: if m is None:
@ -91,18 +96,22 @@ class Fraction(numbers.Rational):
if m.group('sign') == '-': if m.group('sign') == '-':
numerator = -numerator numerator = -numerator
elif isinstance(numerator, numbers.Rational): else:
# Handle copies from other rationals. Integrals get raise TypeError("argument should be a string "
# caught here too, but it doesn't matter because "or a Rational instance")
# denominator is already 1.
other_rational = numerator elif (isinstance(numerator, numbers.Rational) and
numerator = other_rational.numerator isinstance(denominator, numbers.Rational)):
denominator = other_rational.denominator numerator, denominator = (
numerator.numerator * denominator.denominator,
denominator.numerator * numerator.denominator
)
else:
raise TypeError("both arguments should be "
"Rational instances")
if denominator == 0: if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator) raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
numerator = operator.index(numerator)
denominator = operator.index(denominator)
g = gcd(numerator, denominator) g = gcd(numerator, denominator)
self._numerator = numerator // g self._numerator = numerator // g
self._denominator = denominator // g self._denominator = denominator // g

View file

@ -60,13 +60,19 @@ class FractionTest(unittest.TestCase):
self.assertEquals((7, 15), _components(F(7, 15))) self.assertEquals((7, 15), _components(F(7, 15)))
self.assertEquals((10**23, 1), _components(F(10**23))) self.assertEquals((10**23, 1), _components(F(10**23)))
self.assertEquals((3, 77), _components(F(F(3, 7), 11)))
self.assertEquals((-9, 5), _components(F(2, F(-10, 9))))
self.assertEquals((2486, 2485), _components(F(F(22, 7), F(355, 113))))
self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)", self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
F, 12, 0) F, 12, 0)
self.assertRaises(TypeError, F, 1.5) self.assertRaises(TypeError, F, 1.5)
self.assertRaises(TypeError, F, 1.5 + 3j) self.assertRaises(TypeError, F, 1.5 + 3j)
self.assertRaises(TypeError, F, F(1, 2), 3)
self.assertRaises(TypeError, F, "3/2", 3) self.assertRaises(TypeError, F, "3/2", 3)
self.assertRaises(TypeError, F, 3, 0j)
self.assertRaises(TypeError, F, 3, 1j)
def testFromString(self): def testFromString(self):
self.assertEquals((5, 1), _components(F("5"))) self.assertEquals((5, 1), _components(F("5")))

View file

@ -77,6 +77,10 @@ Core and Builtins
Library Library
------- -------
- Issue #5812: For the two-argument form of the Fraction constructor,
Fraction(m, n), m and n are permitted to be arbitrary Rational
instances.
- Issue #5812: Fraction('1e6') is valid: more generally, any string - Issue #5812: Fraction('1e6') is valid: more generally, any string
that's valid for float() is now valid for Fraction(), with the that's valid for float() is now valid for Fraction(), with the
exception of strings representing NaNs and infinities. exception of strings representing NaNs and infinities.