turkadactyl - 1 year ago 76

Python Question

I'm trying to build a rational numbers class that will perform various arithmetic functions based on input values without using the

`fractions`

`print Rational(1,2) * 3`

I've included the code that I have thus far below - the problematic operation is

`__radd__`

`__add__`

`__radd__`

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'

Answer Source

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))
```