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 trialtariqasghar
UX Design Techdegree Graduate 30,519 Points"iadd" method question
In the video, Kenneth needed to return self.value after setting it in the "iadd" function. Why is this necessary?
I was testing this on the workspace and if I don't return self.value in "iadd" function, and just set it, and then print the NumString object, it returns "None".
Thanks.
4 Answers
Jeff Muday
Treehouse Moderator 28,722 PointsOk... thinking this through I do want to change Kenneth's version slightly. At the end of the day the numerical calculations are the same, but Kenneth's version of __iadd__
forces the NumString to change to a new type, and the version I would write would keep its type.
But this is nitpicking because the internal representation self.value becomes converted anyway.... hehehe.
class NumString:
def __init__(self, s):
self.value = s
def __repr__(self):
return str(self.value)
def __float__(self):
return float(self.value)
def __int__(self):
return int(self)
def __add__(self, other):
return float(self.value) + other
def __radd__(self, other):
return float(self.value) + float(other)
def __iadd__(self, other):
self.value = float(self.value) + other
return self.value # I don't like this, see how it changes the type of x below
x = NumString('3.14')
print("x has a type of: ", type(x))
print("x has a value of:", x)
# now, let's use the __add__ property of x
print("x + 1.1 has a type of: ", type(x + 1.1))
print("x + 1.1 has a value of:", x + 1.1)
# now, let's use the __iadd__ property of x
x += 2
print("x += 2 has a type of: ", type(x))
print("x += 2 has a value of:", x)
x += 10
print("x has a type of: ", type(x))
print("x has a value of:", x)
Output. Notice Kenneth's code changes the type of x to float
x has a type of: <class '__main__.NumString'>
x has a value of: 3.14
x + 1.1 has a type of: <class 'float'>
x + 1.1 has a value of: 4.24
x += 2 has a type of: <class 'float'>
x += 2 has a value of: 5.140000000000001
x has a type of: <class 'float'>
x has a value of: 15.14
But if you change the code to return self, you get a "mutable" version, which I think is better.
class NumString:
def __init__(self, s):
self.value = s
def __repr__(self):
return str(self.value)
def __float__(self):
return float(self.value)
def __int__(self):
return int(self)
def __add__(self, other):
return float(self.value) + other
def __radd__(self, other):
return float(self.value) + float(other)
def __iadd__(self, other):
self.value = float(self.value) + other
return self # my modification
Note, the type of x stays as a NumString object with my modification.
x has a type of: <class '__main__.NumString'>
x has a value of: 3.14
x + 1.1 has a type of: <class 'float'>
x + 1.1 has a value of: 4.24
x += 2 has a type of: <class '__main__.NumString'>
x += 2 has a value of: 5.140000000000001
x has a type of: <class '__main__.NumString'>
x has a value of: 15.14
Jeff Muday
Treehouse Moderator 28,722 PointsGreat question! I like that you are thinking through these "magic methods" or "dunder methods" as some people call them. This concept slightly touches on the idea of mutable and immutable objects, but you'll learn more about that later.
__iadd__
is the "inplace addition" operator. It is different than the __add__
method which simply returns the RESULT of the addition to another object. But instead the __iadd__
is 2 operations with one operator... it evaluates first then and replaces itself with a new object.
Since the addition is "inplace" it means that the value of object is modified in place. Its counterparts are __isub__
and iconcat for strings.
x = 3
# the iadd adds and modifies the object, 2 operations in one!
x += 1
print(x)
Hank Tao
7,540 PointsAlso, since Kenneth initialised self.value to type str, shouldn't we keep self.value to type str in the iadd method. i.e.: self.value = str(self + other)
Jeff Muday
Treehouse Moderator 28,722 PointsHank, that is a valid observation. Typically you want consistency of types unless there is an explicit type conversion requested.
TL;DR
I wrote a class that was surprisingly similar for a Geo-telemetry piece. Streams of timestamped latitude and longitude coordinates were downloaded from several different GPS devices (that came from different manufacturers using different formats.) The class would recognize the feed format and serialize the differential ouput to a particular GPS standard output. But I would preserve the original data stream and serialized it to disk-- if anyone needed to prove the veracity of the data, it would be a nearly exact match to the data collected by the GPS devices.
Since we kept the types consistent, the original data could always be produced if anyone needed to assay or reproduce the results.