29

I wrote a class to represent vectors in Python (as an exercise) and I'm having problems with extending the built-in operators.

I defined a __mul__ method for the vector class. The problem is that in the expression x * y the interpreter calls the __mul__ method of x, not y.

So vector(1, 2, 3) * 2 returns a vector <2, 4, 6> just like it should; but 2 * vector(1, 2, 3) creates a TypeError because the built-in int class does not support multiplication by my user-defined vectors.

I could solve this problem by simply writing a new multiplication function

def multiply(a, b): try: return a * b except TypeError: return b * a 

but this would require redefining every function that I want to use with my user-defined classes.

Is there a way to make the built-in function handle this correctly?

2 Answers 2

36

If you want commutativity for different types you need to implement __rmul__(). If implemented, it is called, like all __r*__() special methods, if the operation would otherwise raise a TypeError. Beware that the arguments are swapped:

class Foo(object): def __mul_(self, other): ''' multiply self with other, e.g. Foo() * 7 ''' def __rmul__(self, other): ''' multiply other with self, e.g. 7 * Foo() ''' 
Sign up to request clarification or add additional context in comments.

3 Comments

How does Python know to invoke Foo.__rmul__ and not the __mul__ of the other object?
It attempts to use the __mul__ of the left-hand side, and if it can't find that, then it looks for the __rmul__ of the right-hand side.
@pst, Python calls __mul__ first, but if it either does not exist or if it returns NotImplemented then Python calls __rmul__ of the other object. (Note that if __mul__ raises an execption, __rmul__ is not called.
3

I believe you are looking for __rmul__

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.