From: Jeffrey Yasskin Date: Thu, 14 Feb 2008 06:12:24 +0000 (+0000) Subject: Performance optimizations on Fraction's constructor. X-Git-Tag: v2.6a1~176 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c214d6c942df3fc7af548f7c7e10961dcaba3ee;p=python 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 --- diff --git a/Lib/fractions.py b/Lib/fractions.py index 53ff78549c..9dd49b119f 100755 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -64,7 +64,7 @@ class Fraction(Rational): """ self = super(Fraction, cls).__new__(cls) - if denominator == 1: + if type(numerator) not in (int, long) and denominator == 1: if isinstance(numerator, basestring): # Handle construction from strings. input = numerator @@ -86,24 +86,22 @@ class Fraction(Rational): if m.group('sign') == '-': numerator = -numerator - elif (not isinstance(numerator, numbers.Integral) and - isinstance(numerator, Rational)): - # Handle copies from other rationals. + 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 - 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: raise ZeroDivisionError('Fraction(%s, 0)' % numerator) + numerator = numerator.__index__() + denominator = denominator.__index__() g = gcd(numerator, denominator) - self._numerator = int(numerator // g) - self._denominator = int(denominator // g) + self._numerator = numerator // g + self._denominator = denominator // g return self @classmethod diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index 7929861f87..654456adf6 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -62,11 +62,11 @@ class FractionTest(unittest.TestCase): self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)", F, 12, 0) - self.assertRaises(TypeError, F, 1.5) - self.assertRaises(TypeError, F, 1.5 + 3j) + self.assertRaises(AttributeError, F, 1.5) + self.assertRaises(AttributeError, F, 1.5 + 3j) - self.assertRaises(TypeError, F, F(1, 2), 3) - self.assertRaises(TypeError, F, "3/2", 3) + self.assertRaises(AttributeError, F, F(1, 2), 3) + self.assertRaises(AttributeError, F, "3/2", 3) def testFromString(self): self.assertEquals((5, 1), _components(F("5")))