From f2bfc85dcb6496fadc6423ca44241dd717596871 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 5 Apr 2014 09:29:00 +0100 Subject: Issue #21136: Avoid unnecessary normalization in Fractions resulting from power and other operations. --- Lib/fractions.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'Lib/fractions.py') diff --git a/Lib/fractions.py b/Lib/fractions.py index 79e83ff2c0..43f146f939 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -70,7 +70,7 @@ class Fraction(numbers.Rational): __slots__ = ('_numerator', '_denominator') # We're immutable, so use __new__ not __init__ - def __new__(cls, numerator=0, denominator=None): + def __new__(cls, numerator=0, denominator=None, _normalize=True): """Constructs a Rational. Takes a string like '3/2' or '1.5', another Rational instance, a @@ -165,9 +165,12 @@ class Fraction(numbers.Rational): if denominator == 0: raise ZeroDivisionError('Fraction(%s, 0)' % numerator) - g = gcd(numerator, denominator) - self._numerator = numerator // g - self._denominator = denominator // g + if _normalize: + g = gcd(numerator, denominator) + numerator //= g + denominator //= g + self._numerator = numerator + self._denominator = denominator return self @classmethod @@ -453,10 +456,12 @@ class Fraction(numbers.Rational): power = b.numerator if power >= 0: return Fraction(a._numerator ** power, - a._denominator ** power) + a._denominator ** power, + _normalize=False) else: return Fraction(a._denominator ** -power, - a._numerator ** -power) + a._numerator ** -power, + _normalize=False) else: # A fractional power will generally produce an # irrational number. @@ -480,15 +485,15 @@ class Fraction(numbers.Rational): def __pos__(a): """+a: Coerces a subclass instance to Fraction""" - return Fraction(a._numerator, a._denominator) + return Fraction(a._numerator, a._denominator, _normalize=False) def __neg__(a): """-a""" - return Fraction(-a._numerator, a._denominator) + return Fraction(-a._numerator, a._denominator, _normalize=False) def __abs__(a): """abs(a)""" - return Fraction(abs(a._numerator), a._denominator) + return Fraction(abs(a._numerator), a._denominator, _normalize=False) def __trunc__(a): """trunc(a)""" -- cgit v1.2.1 From bcd8dccf51c716a73884baa8eb3ad84065685a8b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 25 Jul 2014 23:36:00 +0300 Subject: Issue #22033: Reprs of most Python implemened classes now contain actual class name instead of hardcoded one. --- Lib/fractions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Lib/fractions.py') diff --git a/Lib/fractions.py b/Lib/fractions.py index 43f146f939..57bf7f5043 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -280,7 +280,8 @@ class Fraction(numbers.Rational): def __repr__(self): """repr(self)""" - return ('Fraction(%s, %s)' % (self._numerator, self._denominator)) + return '%s(%s, %s)' % (self.__class__.__name__, + self._numerator, self._denominator) def __str__(self): """str(self)""" -- cgit v1.2.1 From 2fb5e9d6937b4e7e52d923b71ad18a22ea10627c Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 24 Sep 2014 08:37:55 +0200 Subject: #22464: Speed up common Fraction operations by special-casing several operations for int-type arguments: constructor and equality test. Also avoid redundant property lookups in addition and subtraction. --- Lib/fractions.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'Lib/fractions.py') diff --git a/Lib/fractions.py b/Lib/fractions.py index 57bf7f5043..5ddc84c1a5 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -104,7 +104,12 @@ class Fraction(numbers.Rational): self = super(Fraction, cls).__new__(cls) if denominator is None: - if isinstance(numerator, numbers.Rational): + if type(numerator) is int: + self._numerator = numerator + self._denominator = 1 + return self + + elif isinstance(numerator, numbers.Rational): self._numerator = numerator.numerator self._denominator = numerator.denominator return self @@ -153,6 +158,9 @@ class Fraction(numbers.Rational): raise TypeError("argument should be a string " "or a Rational instance") + elif type(numerator) is int is type(denominator): + pass # *very* normal case + elif (isinstance(numerator, numbers.Rational) and isinstance(denominator, numbers.Rational)): numerator, denominator = ( @@ -399,17 +407,17 @@ class Fraction(numbers.Rational): def _add(a, b): """a + b""" - return Fraction(a.numerator * b.denominator + - b.numerator * a.denominator, - a.denominator * b.denominator) + da, db = a.denominator, b.denominator + return Fraction(a.numerator * db + b.numerator * da, + da * db) __add__, __radd__ = _operator_fallbacks(_add, operator.add) def _sub(a, b): """a - b""" - return Fraction(a.numerator * b.denominator - - b.numerator * a.denominator, - a.denominator * b.denominator) + da, db = a.denominator, b.denominator + return Fraction(a.numerator * db - b.numerator * da, + da * db) __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub) @@ -561,6 +569,8 @@ class Fraction(numbers.Rational): def __eq__(a, b): """a == b""" + if type(b) is int: + return a._numerator == b and a._denominator == 1 if isinstance(b, numbers.Rational): return (a._numerator == b.numerator and a._denominator == b.denominator) -- cgit v1.2.1