I'm trying to build a rational numbers class that will perform various arithmetic functions based on input values without using the fractions
module. When I'm using two different fractions the code works fine, but as soon as I try to use an integer I'm getting errors in earlier class functions and am unsure why. What I'm trying to implement at this point is, again, adding an integer to a rational number (e.g., print Rational(1,2) * 3
).
I've included the code that I have thus far below - the problematic operation is __radd__
, though when this is included in my code I receive an attribute error for __add__
(this error does not show up until this new operation is included). I'm guessing the problem comes from still having the 2nd __radd__
parameter as other (assuming a different case of the Rational class?), but am unsure how to proceed.
Edit: I'm using Python 2.7. The error from a sample run is included below the code.
def gcd(a, b):
if b == 0:
return a
else:
return gcd(b, a%b)
class Rational:
def __init__(self, nom, denom):
if denom == 0:
raise ZeroDivisionError, ("Cannot divide by zero!")
else:
self.reduce = gcd(nom, denom)
self.nom = nom / self.reduce
self.denom = denom / self.reduce
def __add__ (self, other):
return Rational(self.nom*other.denom+other.nom*self.denom, self.denom*other.denom)
def __sub__ (self, other):
return Rational(self.nom * other.denom - other.nom * self.denom,self.denom * other.denom)
def __mul__ (self, other):
return Rational(self.nom * other.nom, self.denom * other.denom)
def __div__ (self, other):
return Rational(self.nom * other.denom, self.denom * other.nom)
def __radd__ (self, other):
return Rational(self.nom*1+other*self.denom, self.denom*1)
def __str__ (self):
return str(self.nom) + "/" + str(self.denom)
print Rational(1,2) + 1
AttributeError Traceback (most recent call last)
<ipython-input-201-1ccb1fc0dfef> in <module>()
----> 1 print Rational(1,2) + 1
C:\Users\turk\Documents\EV_HW6_P2.py in __add__(self, other)
13 self.denom = denom / self.reduce
14 def __add__ (self, other):
---> 15 return Rational(self.nom*other.denom+other.nom*self.denom, self.denom*other.denom)
16 def __sub__ (self, other):
17 return Rational(self.nom * other.denom - other.nom * self.denom,self.denom * other.denom)
AttributeError: 'int' object has no attribute 'denom'
When Python see Rational
on left side of +
then it uses __and__
but if there is no Rational
on left size but it is on right side then Python use __radd__
. (r
in name __radd__
means right
)
In __add__
you use other.nom
and other.denom
which doesn't exists in int
so Rational(1,2) + 1
doesn't work.
1 + Rational(1,2)
works because in __radd__
you use other
instead of other.nom
and other. denom
You can use isinstance(other, int)
to recognize int
and make different calculation in __add__
and it will works with Rational+int
and Rational+Rational
def __add__ (self, other):
if isinstance(other, int):
# Rational + int
return Rational(self.nom*1+other*self.denom, self.denom*1)
else:
# Rational + Rational
return Rational(self.nom*other.denom+other.nom*self.denom, self.denom*other.denom)
# ----
print(Rational(1,2) + 1)
print(Rational(1,2) + Rational(1,2))