Operator overloading : Instances of different classes

87 views
Skip to first unread message

Prasoon Shukla

unread,
Jul 3, 2013, 10:47:04 AM7/3/13
to sy...@googlegroups.com
In Python, we have special methods that when used in a class definition, overload standard operators.

Now, here's the problem I am having (shown as an example):

Let us say we have a vector - which is an instance of a class that has been subclassed from Basic. Let's call this class Vector. Then, I have a container class, VectMul (subclassed from Mul), that is used to hold any objects of type scalar * vector - much like Mul does. I won't go too deep into what else VectMul class does.

Anyway, now, I have defined a method Vector.__mul__ which is supposed to return a VectMul after performing appropriate checks on the input.

At this point, let me just refresh your memory : if x and y are python objects, then:
x + y => x.__add__(y)
y + x => y.__add__(x)

Back to my question. So, when a user does:

  • Vector*Vector, the Vector.__mul__ method will raise an error saying that a user cannot multiply two vectors.
  • Vector*scalar, the Vector.__mul__ will be called and a VectMul will be returned.
  • scalar*Vector : Now this is the problem - here let us say that scalar is a Add - then the method Add.__mul__ will be called instead of what I want to be called  - in this case, Vector.__mul__ - and return a Mul object instead of a VectMul.
This is the problem I face right now. I googled around a bit - apparently, we can use the __rmul__ method. But, for that to work - the Add.__mul__ (in the third point above) should return NotImplemented (what does that even mean? Raise an exception?). Obviously, I shouldn't have to change Add.__add__ for this. So, how can I handle this problem?

Julien Rioux

unread,
Jul 3, 2013, 11:19:18 AM7/3/13
to sy...@googlegroups.com
On Wednesday, 3 July 2013 10:47:04 UTC-4, Prasoon Shukla wrote:
Back to my question. So, when a user does:

  • Vector*Vector, the Vector.__mul__ method will raise an error saying that a user cannot multiply two vectors.
  • Vector*scalar, the Vector.__mul__ will be called and a VectMul will be returned.
  • scalar*Vector : Now this is the problem - here let us say that scalar is a Add - then the method Add.__mul__ will be called instead of what I want to be called  - in this case, Vector.__mul__ - and return a Mul object instead of a VectMul.
This is the problem I face right now. I googled around a bit - apparently, we can use the __rmul__ method. But, for that to work - the Add.__mul__ (in the third point above) should return NotImplemented (what does that even mean? Raise an exception?). Obviously, I shouldn't have to change Add.__add__ for this. So, how can I handle this problem?


_op_priority and the @call_highest_priority are there exactly for this purpose. Define it in your class with a value above 10.0, which is Expr's default value for it. Also define __rmul__, using the decorator @call_highest_priority. This will allow your class to control what happens during multiplication (left or right).

Cheers,
Julien

Frédéric Bastien

unread,
Jul 3, 2013, 11:19:27 AM7/3/13
to sympy
Hi,

I think changing Add.__add__ to return NotImplemented is the right solution. This is the Python behavior for what you want. Python will raise an error if Add.__add__ return NotImplemented and y.__radd__(x) don't work.

There isn't any other way to do this to my knowledge.

Frédéric



--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages