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:
class Foo(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 -= 360
while val < 0:
val += 360
return val
def __iadd__(self, other):
"""Augmented addition assignment."""
print "Foo.iadd"
val = self.__add__(other)
self.angle = val
f = Foo()
f += 20
print f is None
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:
class Angle(object):
def __init__(self, angle):
self.angle = angle % 360
def __add__(self, other):
return Angle(self.angle + other.angle)
def __iadd__(self, other):
return self.__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:
class Angle(int):
def __init__(self, val):
self.val = val % 360
def __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 ok
return 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"