summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-04-24 14:06:19 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-04-24 14:06:19 (GMT)
commitd4d95f8eac4718809cfb68f97c9881586596100a (patch)
treed9a603aa84d7d9f45a0937ae91163e8f2d4153de /Lib
parentf21bd3cc2f5c7def415677dae85ea9383c7a571d (diff)
downloadcpython-d4d95f8eac4718809cfb68f97c9881586596100a.zip
cpython-d4d95f8eac4718809cfb68f97c9881586596100a.tar.gz
cpython-d4d95f8eac4718809cfb68f97c9881586596100a.tar.bz2
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. ........
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/fractions.py33
-rw-r--r--Lib/test/test_fractions.py8
2 files changed, 28 insertions, 13 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py
index 5242f8f..fcebb4f 100755
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -54,7 +54,7 @@ class Fraction(numbers.Rational):
__slots__ = ('_numerator', '_denominator')
# 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.
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)
- if not isinstance(numerator, int) and denominator == 1:
- if isinstance(numerator, str):
+ if denominator is None:
+ if isinstance(numerator, numbers.Rational):
+ self._numerator = numerator.numerator
+ self._denominator = numerator.denominator
+ return self
+
+ elif isinstance(numerator, str):
# Handle construction from strings.
m = _RATIONAL_FORMAT.match(numerator)
if m is None:
@@ -91,18 +96,22 @@ class Fraction(numbers.Rational):
if m.group('sign') == '-':
numerator = -numerator
- elif isinstance(numerator, numbers.Rational):
- # Handle copies from other rationals. Integrals get
- # caught here too, but it doesn't matter because
- # denominator is already 1.
- other_rational = numerator
- numerator = other_rational.numerator
- denominator = other_rational.denominator
+ else:
+ raise TypeError("argument should be a string "
+ "or a Rational instance")
+
+ elif (isinstance(numerator, numbers.Rational) and
+ isinstance(denominator, numbers.Rational)):
+ numerator, denominator = (
+ numerator.numerator * denominator.denominator,
+ denominator.numerator * numerator.denominator
+ )
+ else:
+ raise TypeError("both arguments should be "
+ "Rational instances")
if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
- numerator = operator.index(numerator)
- denominator = operator.index(denominator)
g = gcd(numerator, denominator)
self._numerator = numerator // g
self._denominator = denominator // g
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index 448e32d..e321914 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -60,13 +60,19 @@ class FractionTest(unittest.TestCase):
self.assertEquals((7, 15), _components(F(7, 15)))
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)",
F, 12, 0)
self.assertRaises(TypeError, F, 1.5)
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, 0j)
+ self.assertRaises(TypeError, F, 3, 1j)
+
def testFromString(self):
self.assertEquals((5, 1), _components(F("5")))