mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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:
parent
f21bd3cc2f
commit
d4d95f8eac
3 changed files with 32 additions and 13 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue