I have this class which works with fractions (e.g. (1,2), (3,4) etc):
class Fraction(object):
def __init__(self, num=0, denom=1):
''' Creates a new Fraction with numberator num and denominator denom'''
self.numerator = num
if denom != 0:
self.denominator = denom
else:
raise ZeroDivisionError
def __str__(self):
'''Returns the string numerator/denominator '''
return "{0}/{1}".format(self.numerator, self.denominator)
def __repr__(self):
"""blah"""
return Fraction(self.numerator, self.denominator)
And I want to have a sub-class Mixed number which can accept both a whole number and a fraction (e.g. 2 Fraction(1,2), 3 Fraction (3,4) etc). I'm not sure how to do this however, Any help as to how to do this would be appreciated
class MixedNumber(Fraction):
2 Answers 2
There are two ways that immediately come to mind when thinking of implementing a MixedNumber class with a Fraction class provided. One way is as @HunterMcMillen suggests, is to have the class use composition, which is to utilize distinct objects to represent the whole number, and fraction parts, respectively. This gives you access to each objects specialized methods inside your class, which can be handy if the components you're building from have distinct behaviors each encapsulates.
class MixedNumber(object):
def __init__(self, whole_number, fraction):
self.whole_number = whole_number
self.fraction = fraction
def __str__(self):
if self.fraction.numerator == 0:
return str(self.whole_number)
elif self.whole_number == 0:
return str(self.fraction)
else:
return '{} {}'.format(self.whole_number,self.fraction)
def __repr__(self):
return 'MixedNumber({},{!r})'.format(self.whole_number,self.fraction)
The other possibility is inheritance, if your Fraction class supports improper fractions, then you can use a subclass to appropriately handle initialization and string rendering in mixed number format, as follows:
class MixedNumber(Fraction):
def __init__(self, whole_number, fraction):
num = whole_number * fraction.denominator + fraction.numerator
super(MixedNumber,self).__init__(num, fraction.denominator)
def __str__(self):
# assume positive fractions for demonstration only
q, r = divmod(self.numerator,self.denominator)
if r == 0:
return str(q)
elif q == 0:
return super(MixedNumber,self).__str__()
else:
return '{} {}/{}'.format(q,r,self.denominator)
def __repr__(self):
q, r = divmod(self.numerator, self.denominator)
return 'MixedNumber({},Fraction({},{}))'.format(q,r,self.denominator)
Your Fraction.__repr__ method should return a string that when passed into eval should instantiate something equal to the source object, i.e. eval(frac) == frac. See this stack overflow question for more details on the distinction between __str__ and __eval__.
Comments
I recently finished writing class Mixed that inherits from the standard library Fraction class. It would probably be a good guide on how to use existing functionality of the parent class. The source is HERE. It accepts as input anything that the library Fraction class accepts as well as string representations of mixed numbers such as Mixed('3 4/5') or rational whole_number/numerator/denominator sets as in Mixed(3,4,5). All of the functionality of Fraction has been preserved. __str__ and __repr__ would yield 3 4/5 and Mixed(3,4,5) respectively. It makes conversion to float or standard Fraction as easy as float(m) or Fraction(m). Cheers
MixedNumberto inherit fromFraction. It would make more sense to compose aFractioninto theMixedNumberclass.MixedNumberseems not suitable to inherit fromFraction.