Search code examples
pythonclassfractions

Python class adding fractions


I have this class which takes a whole number and a fraction, and adds them together. The problem, however, is that the __add__ function here converts the answer to a __str__ so when I try and print the __repr__ on the answer to an added question it just prints a str of the answer.

from fractions import Fraction

class MixedNumber(object):
   def __init__(self, whole_number, fraction):
        self.whole_number = whole_number
        self.fraction = fraction

   def __repr__(self):
       return "MixedNumber({}, Fraction({}, {})".format(self.whole_number, self.fraction.numerator, self.fraction.denominator)

   def __add__(self, g):
       summed = 0
       for v in (self.whole_number, g.whole_number, self.fraction, g.fraction):
           summed = Fraction(summed.numerator * v.denominator +
                          v.numerator * summed.denominator,
                          summed.denominator * v.denominator)
       whole = summed.numerator // summed.denominator
       remainder = Fraction(summed.numerator * whole.denominator -
                     whole.numerator * summed.denominator,
                     summed.denominator * whole.denominator)
       return '{} and {}'.format(whole,remainder)

if __name__=='__main__':
    x = MixedNumber(3, Fraction(1, 3))
    y = MixedNumber(-1, Fraction(2, 5))
    z = x + y
    print(z)
print(z.__repr__())

For example: The output to this is

2 and 11/15
'2 and 11/15'

When it should be

2 and 11/15
MixedNumber(2, Fraction(11, 15))

Any help fixing this problem would be much appreciated.


Solution

  • Return a new instance of MixedNumber instead:

    return MixedNumber(whole, remainder)
    

    or, to make it more sub-class-friendly, of type(self):

    return type(self)(whole, remainder)
    

    Now your code prints:

    >>> x = MixedNumber(3, Fraction(1, 3))
    >>> y = MixedNumber(-1, Fraction(2, 5))
    >>> z = x + y
    >>> print z
    MixedNumber(2, Fraction(11, 15)
    >>> print repr(z)
    MixedNumber(2, Fraction(11, 15)
    

    but you could print the old result of __add__ explicitly:

    >>> print '{} and {}'.format(z.whole_number, z.fraction)
    2 and 11/15
    

    You could make that your __str__ method:

    def __str__(self):
        return '{} and {}'.format(z.whole_number, z.fraction)
    

    after which your print statements would be:

    >>> print z
    2 and 11/15
    >>> print repr(z)
    MixedNumber(2, Fraction(11, 15)