Kaydet (Commit) 1c214d6c authored tarafından Jeffrey Yasskin's avatar Jeffrey Yasskin

Performance optimizations on Fraction's constructor.

  ./python.exe -m timeit -s 'from fractions import Fraction' 'Fraction(3)`
31.7 usec/loop -> 9.2 usec/loop

  ./python.exe -m timeit -s 'from fractions import Fraction' 'Fraction(3, 2)'`
27.7 usec/loop -> 9.32 usec/loop

  ./python.exe -m timeit -s 'from fractions import Fraction; f = Fraction(3, 2)' 'Fraction(f)'
31.9 usec/loop -> 14.3 usec/loop
üst abe32371
...@@ -64,7 +64,7 @@ class Fraction(Rational): ...@@ -64,7 +64,7 @@ class Fraction(Rational):
""" """
self = super(Fraction, cls).__new__(cls) self = super(Fraction, cls).__new__(cls)
if denominator == 1: if type(numerator) not in (int, long) and denominator == 1:
if isinstance(numerator, basestring): if isinstance(numerator, basestring):
# Handle construction from strings. # Handle construction from strings.
input = numerator input = numerator
...@@ -86,24 +86,22 @@ class Fraction(Rational): ...@@ -86,24 +86,22 @@ class Fraction(Rational):
if m.group('sign') == '-': if m.group('sign') == '-':
numerator = -numerator numerator = -numerator
elif (not isinstance(numerator, numbers.Integral) and elif isinstance(numerator, Rational):
isinstance(numerator, Rational)): # Handle copies from other rationals. Integrals get
# Handle copies from other rationals. # caught here too, but it doesn't matter because
# denominator is already 1.
other_rational = numerator other_rational = numerator
numerator = other_rational.numerator numerator = other_rational.numerator
denominator = other_rational.denominator denominator = other_rational.denominator
if (not isinstance(numerator, numbers.Integral) or
not isinstance(denominator, numbers.Integral)):
raise TypeError("Fraction(%(numerator)s, %(denominator)s):"
" Both arguments must be integral." % locals())
if denominator == 0: if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator) raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
numerator = numerator.__index__()
denominator = denominator.__index__()
g = gcd(numerator, denominator) g = gcd(numerator, denominator)
self._numerator = int(numerator // g) self._numerator = numerator // g
self._denominator = int(denominator // g) self._denominator = denominator // g
return self return self
@classmethod @classmethod
......
...@@ -62,11 +62,11 @@ class FractionTest(unittest.TestCase): ...@@ -62,11 +62,11 @@ class FractionTest(unittest.TestCase):
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(AttributeError, F, 1.5)
self.assertRaises(TypeError, F, 1.5 + 3j) self.assertRaises(AttributeError, F, 1.5 + 3j)
self.assertRaises(TypeError, F, F(1, 2), 3) self.assertRaises(AttributeError, F, F(1, 2), 3)
self.assertRaises(TypeError, F, "3/2", 3) self.assertRaises(AttributeError, F, "3/2", 3)
def testFromString(self): def testFromString(self):
self.assertEquals((5, 1), _components(F("5"))) self.assertEquals((5, 1), _components(F("5")))
......
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