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 trialFlore W
4,744 PointsWhat is the purpose of the __iadd__ magic method, since it works fine without it?
I know this question has been asked previously, but it didn't shatter my doubts: I get the exact same result in the console with or without the iadd method.
>>> five = Numstring(5)
>>> five += 1
>>> five
6
In which case would iadd add any value? Thanks!
4 Answers
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsHello Flore Wang
So the main difference between __add__
and __iadd__
is that __iadd__
is actually storing that value its adding into the self.value
.
Example: If this is my class.
class NumString:
def __init__(self, value):
self.value = str(value)
def __int__(self):
return int(self.value)
def __str__(self):
return self.value
def __add__(self, other):
return int(self) + other
def __iadd__(self, other):
self.value = self + other
return self.value
Now if I did the following with my class.
some_num1 = NumString(0) # Create an instance of NumString with 0 as value.
str(some_num1) # Check what is contained within self.value in this instance.
# Output: '0'
some_num1 + 1 # We add some_num1 to 1, this returns back the calculation using the __add__ method
str(some_num1) # check what some_num1 is holding for a self.value
# Output: '0'
some_num1 += 2 # We in-place add some_num1 to 2, this stores and returns the new stored value using __iadd__ method.
str(some_num1) # check what some_num1 is holding now?
# Output: '2'
Can you see how __iadd__
is storing the calculated value self.value
and the __add__
method is just calculating and returning it but NOT storing it.
Flore W
4,744 PointsHi Chris, thanks a lot! I tried deleting the line
def __iadd__(self, other):
self.value = self + other
return self.value
and it returns exactly the same if I perform
>>>some_num = NumString(0)
>>>some_num +=2
>>>str(some_num)
#returns '2'
How come?
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsHey Flore Wang
This is because if you dont define, or even if you do define your own __iadd__()
method. The __add__()
method is called fro
So if you run this code. You will see
class NumString:
def __init__(self, value):
self.value = str(value)
def __int__(self):
return int(self.value)
def __str__(self):
return self.value
def __add__(self, other):
print('This is from __add__()')
return int(self) + other
def __iadd__(self, other):
print('This came from __iadd__()')
self.value = self + other
return self.value
Once you define this you can run something like
ns1 = NumString(5)
ns1 += 1
# output: This came from __iadd__()
# output: This is from __add__()
Then if you remove that __iadd__
method, you will see that it still prints __add__
print statement because it still uses it as a fallback for +=
Flore W
4,744 PointsHey Chris, thanks again for the detailed explanation, I really like the fact that you have added "print('This is from add()')", it's super useful for debugging.
I have tried your code and I still get the same result with or without iadd.
So with iadd (exactly the code you posted above), I get:
>>> nb = NumString(0)
>>> nb += 1
This is from __iadd__()
This is from __add__()
>> print(nb)
1
And without iadd, I get:
>>> nb = NumString(0)
>>> nb += 1
This is from __add__()
>> print(nb)
1
The add method alone has stored my new value! I thought that was iadd's role?
Alternatively, when I delete add and only keep iadd, I get a TypeError.
>>> nb = NumString(0)
>>> nb += 1
This is from __iadd__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/treehouse/workspace/numstring2.py", line 14, in __iadd__
self.value = self + other
TypeError: unsupported operand type(s) for +=: "NumString" and "int"
I am confused as to iadd 's role. It seems that add can do pretty much everything that iadd has to do (storing the value), so why do we still need it?
MIAN OSAMA ARSHAD
Courses Plus Student 279 PointsHi it does not make sense
Why
some_num + 1
return zero in both cases with and without iadd
some_num += 1
print 1 in both cases with and without i add
Akanksha Singh
5,083 PointsAs already discussed, we know that if iadd is not defined we go to add, the purpose of iadd is to assign a value to the instance itself, in case of +=, so if you change the functionality of iadd to something other than add, you will have the power to customize the +=.
Example :
class NumString:
def __init__(self,value):
self.value = str(value)
def __str__(self):
return self.value
def __int__(self):
return int(self.value)
def __float__(self):
return float(self.value)
def __add__(self, other):
if('.' in self.value):
return float(self) + other
return int(self) + other
def __radd__(self, other):
return self + other
def __iadd__(self,other):
self.value = int(self.value) + 45 + other
return self.value
four = NumString(4)
print ( str(four) + "hi")
print (type (int(four)))
print(type (float(four)))
two = 5 + four
print(two) #prints 9
four += 1
print(four) #print 47
MIAN OSAMA ARSHAD
Courses Plus Student 279 PointsAfter Reading All The Comments . Your Comment Is To The Point
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsYes, so the TypeError occurs at that point because Python doesnt know how to perform the operation between these type separate data types right? It has no way of knowing how to convert a NumString
to an Int
or an Int to a NumString to perform +
on it. It just goes, "Uh oh I have no idea how to ADD a NumString to this Integer type. So best thing I can do is raise
a TypeError
The logic that you wrote inside:
def __add__(self, other):
# The logic in here told the object how to react to the thing it was getting + to.
# without the logic for this method, Python doesnt know what to do when it encounters
# NumType(0) + 10 because they are two different data types technically
Sebastiaan van Vugt
Python Development Techdegree Graduate 13,554 PointsI see how iadd gets involved when "+=" is being used but like Flore W I still don't see the use. If you leave it out add will do the job anyway and iadd doesn't seem to be capable of doing anything without add. When would I therefore ever want to use iadd?
Responding to the reply below:
I guess what puzzled me most is trying to think of a situation when iadd would come in handy.
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsIt isnt absolutely necessary to implement __iadd__
The +=
operator is shorthand.
The statement
nb += 1
is the same as saying
nb = nb + 1
So if you dont implement __iadd__
python will just fallback on the __add__
method. But if you do implement the __iadd__
method Python will attempt to use it.
Mark Chesney
11,747 PointsHi. I read the above dialogue and have this question. Can you use += on integers without implementing iadd , say for example, by instantiating NumString? Thanks
Quinton Rivera
5,177 PointsQuinton Rivera
5,177 PointsWhy doesnt it work if we place the code from inside of iadd and place it inside of the add method? The only difference i see is that inside of the iadd method you assign the value so you can store it, does python not let you store inside of the add method, im sure why we couldnt add that type of functionality to the code.