diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-04-24 13:56:07 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-04-24 13:56:07 (GMT) |
commit | 4af8e745c4a8a225af3c3025909a8c042aafcca0 (patch) | |
tree | 0f7ee07290b4f2740483a6ca0ac00ebf49a1833a | |
parent | 90d47cb46c5845d15bc4fdc0590e19e58e894e0c (diff) | |
download | cpython-4af8e745c4a8a225af3c3025909a8c042aafcca0.zip cpython-4af8e745c4a8a225af3c3025909a8c042aafcca0.tar.gz cpython-4af8e745c4a8a225af3c3025909a8c042aafcca0.tar.bz2 |
Issue #5812: The two-argument form of the Fraction constructor
now accepts arbitrary Rational instances.
-rwxr-xr-x | Lib/fractions.py | 33 | ||||
-rw-r--r-- | Lib/test/test_fractions.py | 8 | ||||
-rw-r--r-- | Misc/NEWS | 4 |
3 files changed, 32 insertions, 13 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py index 7db6b5b..15711ed 100755 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -56,7 +56,7 @@ class Fraction(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 Fraction. Takes a string like '3/2' or '1.5', another Fraction, or a @@ -65,8 +65,13 @@ class Fraction(Rational): """ self = super(Fraction, cls).__new__(cls) - if type(numerator) not in (int, long) and denominator == 1: - if isinstance(numerator, basestring): + if denominator is None: + if isinstance(numerator, Rational): + self._numerator = numerator.numerator + self._denominator = numerator.denominator + return self + + elif isinstance(numerator, basestring): # Handle construction from strings. m = _RATIONAL_FORMAT.match(numerator) if m is None: @@ -93,18 +98,22 @@ class Fraction(Rational): if m.group('sign') == '-': numerator = -numerator - elif isinstance(numerator, 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, Rational) and + isinstance(denominator, 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 a180912..1d71dd7 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"))) @@ -244,6 +244,10 @@ Core and Builtins 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 that's valid for float() is now valid for Fraction(), with the exception of strings representing NaNs and infinities. |