turkadactyl turkadactyl - 1 year ago 115
Python Question

Multiplying Fractions and Integers in Python

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

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
, though when this is included in my code I receive an attribute error for
(this error does not show up until this new operation is included). I'm guessing the problem comes from still having the 2nd
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
return gcd(b, a%b)
class Rational:
def __init__(self, nom, denom):
if denom == 0:
raise ZeroDivisionError, ("Cannot divide by zero!")
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)

Sample error

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) 
        # 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))
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download