Forward, Reverse and In-Place
Every arithmetic operator is transformed into a method call.
By defining the numeric special methods, your class will work
with the built-in arithmetic operators.
First, there are as many as three variant methods required to
implement each operation.
For example, * is implemented by __mul__, __rmul__ and __imul__
There are forward and reverse special methods so that you can assure that your
operator is properly commutative.
You don't need to implement all three versions.
The reverse name is used for special situations that involve objects of
multiple classes.
Lecture06COMPSCI 10517
class Fraction:
...
def __mul__(self, other):
new_num = self.num * other.num
new_den = self.den * other.den
return Fraction(new_num, new_den)
mul Vs rmul
Locating an appropriate method for an operator
First, it tries a class based on the left-hand operand using the
"forward" name. If no suitable special method is found, it tries the
right-hand operand, using the "reverse" name.
Version 1:
Lecture06COMPSCI 10518
x = Fraction(2,3)
y = Fraction(1,3)
p = x * y
print(p)
P = x * 2
2/9
AttributeError: 'int' object
has no attribute 'num'
Invoke x.__mul__(y)
class Fraction:
...
def __mul__(self, other):
if isinstance(other,Fraction):
new_num = self.num * other.num
new_den = self.den * other.den
return Fraction(new_num, new_den)
else:
new_num = self.num * other
return Fraction(new_num, self.den)
Version 2
Check the type of the right operand:
Lecture06COMPSCI 10519
x = Fraction(2,3)
y = Fraction(1,3)
p = x * y
print(p)
P = x * 2
print(p)
P = 2 * x
2/9
If the right operand
is not a Fraction
4/3
TypeError: unsupported operand
type(s) for *: 'int' and
'Fraction'
class Fraction:
...
def __mul__(self, other):
if isinstance(other,Fraction):
...
def __rmul__(self, other):
new_num = self.num * other
return Fraction(new_num, self.den)
Version 3
If the left operand of * is a primitive type and the right operand is a
Fraction, Python invokes __rmul__
Lecture06COMPSCI 10520
x = Fraction(2,3)
y = Fraction(1,3)
p = x * y
print(p)
P = x * 2
print(p)
P = 2 * x
2/9
4/3
4/3
Invoke x.__rmul__(2)