Commit d4d95f8e authored by Mark Dickinson's avatar Mark Dickinson

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.
........
parent f21bd3cc
...@@ -54,7 +54,7 @@ class Fraction(numbers.Rational): ...@@ -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): ...@@ -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): ...@@ -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
......
...@@ -60,13 +60,19 @@ class FractionTest(unittest.TestCase): ...@@ -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")))
......
...@@ -77,6 +77,10 @@ Core and Builtins ...@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment