Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialAkshaan Mazumdar
3,787 PointsIn the last magic method - radd- Kenneth says something which has me confused!! >>> int(self) + other VS self + other
In the r_add function we do int(self) + other , which I understand will add self.value and other
BUT ! Kenneth also says that if we do self + other it will be the same .
Please elaborate how it will be same?
1 Answer
Chris Freeman
Treehouse Moderator 68,457 PointsGreat question! Let's step through what is happening.
When a Die is added to another Die, the following happens
In the r_add function we do int(self) + other , which I understand will add self.value and other
BUT ! Kenneth also says that if we do self + other it will be the same .
The method __radd__
, a reflected add, is called when D6
is on the right side of the addition operator.
The code below (with return int(self) + other
) produces the following results. Comments added after output.
$ python
Python 3.6.3 (default, Oct 3 2017, 21:45:48)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dice import *
>>> d1 = D6(value= 2)
running D6.__init__ # called when instantiating D6
running Die.__init__ # called by super from D6
>>> d2 = D6(value= 6)
running D6.__init__ # called when instantiating D6
running Die.__init__ # called by super from D6
>>> d1 + d2
running D6.__add__ # d1 on left side of operator call, so call d1.__add__ with other = d2
running Die.__int__ # d1.__add__ calls int(self) which calls the parent's __int__ => gets int value 2
# now has 2 + d2
running D6.__radd__ with int(self) # d2 on right side of operator, so call d2.__radd__ with other=2
running Die.__int__ # d2.__radd__ calls parents __int__ on itself => gets integer value 6
# now has 6 + 2
8
If the __radd__
is changed to use self + other
then the addition flow changes:
>>> d1 + d2
>>> d1 + d2
running D6.__add__ # d1 on left side of operator call its __add__ with other = d2
running Die.__int__ # d1.__add__ calls int(self) which calls the parent's __int__ => gets int value 2
# now has 2 + d2
# -- same to this point --
running D6.__radd__ with self + other # d2 on right side of operator, so call d2.__radd__ with other=2
# now has d2 + 2
running D6.__add__ #d2 now on left side of operator, so call d2.__add__ with other=2
running Die.__int__ # d2.__add__ calls int(self) which calls the parent's __int__ => gets int value 6
# now has 6 + 2
8
So, in the end, using int(self) saves one method call.
Code used in above output:
import random
class Die:
def __init__(self, sides=2, value=0):
print("running Die.__init__")
if not sides >= 2:
raise ValueError("Must have at least 2 sides")
if not isinstance(sides, int):
raise ValueError("Sides must be a whole number")
self.value = value or random.randint(1, sides)
def __int__(self):
print("running Die.__int__")
return self.value
class D6(Die):
def __init__(self, value=0):
print("running D6.__init__")
super().__init__(sides=6, value=value)
def __eq__(self, other):
print("running D6.__eq__")
return int(self) == other
def __ne__(self, other):
print("running D6.__ne__")
return int(self) == other
def __gt__(self, other):
print("running D6.__gt__")
return int(self) > other
def __lt__(self, other):
print("running D6.__le__")
return int(self) < other
def __ge__(self, other):
print("running D6.__ge__")
return int(self) > other or int(self) == other
def __le__(self, other):
print("running D6.__le__")
return int(self) < other or int(self) == other
def __add__(self, other):
print("running D6.__add__")
return int(self) + other
def __radd__(self, other):
print("running D6.__radd__ with int(self)")
return int(self) + other