Python Magic Method Augmented Assignment Misunderstanding
Solution 1:
About __iadd__
(and other __iXXX__
methods):
These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self).
Your __iadd__
method doesn't "assigns a nonetype to self.angle
", it returns None
(default value when a function has no explicit return), and this rebinds your current name to None
, ie:
classFoo(object):
def__init__(self, angle=120):
self.angle = angle
def__add__(self, other):
"""Check for recursion, then return the added value."""print"Foo.add"
val = self.angle + other
while val > 360:
val -= 360while val < 0:
val += 360return val
def__iadd__(self, other):
"""Augmented addition assignment."""print"Foo.iadd"
val = self.__add__(other)
self.angle = val
f = Foo()
f += 20print f isNone
To make a long story short : you want __iadd__
to return something meaningfull, most probably self
.
Solution 2:
Both __add__
and __iadd__
should return
an Angle
object:
classAngle(object):def__init__(self, angle):
self.angle = angle % 360def__add__(self, other):
return Angle(self.angle + other.angle)
def__iadd__(self, other):
returnself.__add__(other)
Note use of angle % 360
to keep angle in range(0, 360)
.
Solution 3:
Just delete your __iadd__
method completely.
This will make +=
operator fall back onto __add__
, which is the preferred behaviour for objects which model immutable types.
Example:
classAngle(int):def__init__(self, val):
self.val = val % 360def__add__(self, other):
return Angle(self.val + other)
def__sub__(self, other):
return Angle(self.val - other)
def__neg__(self):
return Angle(-self.val)
def__repr__(self):
# just for demonstration purposes okreturn str(self.val)
Let's try it out...
>>>a = Angle(35)>>>a
35
>>>a + 400
75
>>>a
35
>>>a += 400>>>a
75
>>>a - 75
0
>>>a - 76
359
>>>a
75
>>>a -= 76>>>a
359
No __iadd__
or __radd__
is needed, let python handle the magic for you.
Solution 4:
You need to return self
from the implementation of __iadd__
since the return value of __iadd__
is assigned to the left hand side of the +=
operator. This is what the Python documentation says about the implementation of in-place operators:
These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self).
(source)
Post a Comment for "Python Magic Method Augmented Assignment Misunderstanding"