Reordering operations for __add__, __mul__ methods, etc. In custom class

I have a vector class:

class Vector: def __init__(self, x, y): self.x, self.y = x, y def __str__(self): return '(%s,%s)' % (self.x, self.y) def __add__(self, n): if isinstance(n, (int, long, float)): return Vector(self.x+n, self.y+n) elif isinstance(n, Vector): return Vector(self.x+nx, self.y+ny) 

which works great i.e. I can write:

 a = Vector(1,2) print(a + 1) # prints (2,3) 

However, if the order of operations is canceled, then it fails:

 a = Vector(1,2) print(1 + a) # raises TypeError: unsupported operand type(s) # for +: 'int' and 'instance' 

I understand the error: adding an int object to a Vector object is undefined because I did not define it in the int class. Is there a way around this without defining it in the int class (or the parent int )?

+5
source share
2 answers

You need to also define __radd__

Some operations do not necessarily evaluate to a + b == b + a and why Python defines add and radd methods .

Explaining himself better: he supports the fact that "int" does not define a + operation with class Vector instances as part of the operation. Therefore, the vector + 1 does not coincide with the vector 1 +.

When Python tries to see what method 1.__add__ can do, an exception is thrown. And Python goes and searches for a Vector.__radd__ operation to try to complete it.

In the case of OP, the estimate is true and has the value __radd__ = __add__

 class Vector(object): def __init__(self, x, y): self.x, self.y = x, y def __str__(self): return '(%s,%s)' % (self.x, self.y) def __add__(self, n): if isinstance(n, (int, long, float)): return Vector(self.x+n, self.y+n) elif isinstance(n, Vector): return Vector(self.x+nx, self.y+ny) __radd__ = __add__ a = Vector(1, 2) print(1 + a) 

What outputs:

 (2,3) 

The same applies to all numerical operations.

+5
source

When you say x + y , Python calls x.__add__(y) . If x does not implement __add__ (or this method returns NotImplemented ), Python tries to call y.__radd__(x) as a backup.

So all you have to do is define the __radd__() method in your Vector class, and 1 + y will work as you expected.

Note: you will also need to do the same for other operations, for example. implement a pair of __mul__() and __rmul__() , etc.

You can also look at this question , it explains in more detail the same principle.

Update: Depending on your use case, you may also implement a method

+4
source

Source: https://habr.com/ru/post/1240753/


All Articles