Skip to content Skip to sidebar Skip to footer

Python Magic Method Augmented Assignment Misunderstanding

I'm creating a simple angle object which is, in it's simplest forms, an integer value that recurs when it goes above 360 (back to 0) or below 0 (back to 360). I implemented the mag

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"