[Python-bugs-list] [ python-Bugs-531355 ] surprise overriding __radd__ in subclass of complex
noreply@sourceforge.net
noreply@sourceforge.net
Fri, 22 Mar 2002 19:18:23 -0800
Bugs item #531355, was opened at 2002-03-18 09:32
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=531355&group_id=5470
>Category: Documentation
>Group: Python 2.3
Status: Open
Resolution: None
>Priority: 1
Submitted By: Arthur Siegel (aj_siegel)
>Assigned to: Fred L. Drake, Jr. (fdrake)
Summary: surprise overriding __radd__ in subclass of complex
Initial Comment:
I had presented this on tutor and python-list:
class Complex(complex):
def __mul__(self,other):
other=Complex(other)
t = complex.__mul__(self,other)
return Complex(t.real,t.imag)
__rmul__ = __mul__
def __add__(self,other):
other=Complex(other)
return Complex(self.real.__add__
(other.real),self.imag.__add__(other.imag))
__radd__ = __add__
Then:
print type(Complex(5,4) * 7)
>><class '__main__.Complex'>
print type(7 * Complex(5,4))
>><class '__main__.Complex'>
print type(Complex(5,4) + 7)
>><class '__main__.Complex'>
But:
print type(7 + Complex(5,4))
>><type 'complex'>
Danny Yoo, after looking into it pretty deeply -
and going to the docs and source gace me this
advice.
"In any case, this is definitely a bug in the
documentation. Arthur, bring
it up on comp.lang.python and Sourceforge again.
Someone should really
look at your example, since it does seem serious... if
not a little
obscure. *grin* "
----------------------------------------------------------------------
>Comment By: Guido van Rossum (gvanrossum)
Date: 2002-03-22 22:18
Message:
Logged In: YES
user_id=6380
It seems that * is the exception -- all other operators (+,
-, /, **) return the type of the left operand. It gets even
weirder if we change the left operand from 7 to 7.0 -- then
* is no longer an exception and returns a complex like all
other operators!
The weirdness is in int_mul. If the right argument is not an
int but a sequence that implements the sq_repeat slot, it
invokes that. But if you create a class that defines
__mul__, that implements the sequence repeat slot! (Python
doesn't know if you intend to implement a seqence or a
number, when you define a __mul__ method, so it maps both
the nb_multiply and the sq_repeat slots to the __mul__
method).
So 7 + Complex() takes the path through int_mul that calls
the Complex.__mul__ , and that's why you get a Complex value
back. Floats can't be used in the sequence repeat operator,
so its multiply is "normal".
But wait...! There's another mystery. Ints don't know how to
add themselves to complex numbers! So why wouldn't
7+Complex() use the normal pattern of (a) try the left
operand, (b) if that returns NotImplemented, try the right
operand? The answer is that complex numbers implement
coercion! And in that case, step (b) is modified to (b) ask
either operand to perform a coercion, and if it succeeds,
ask the left operand of the resulting coerced pair to
perform the operation. So complex coerces the int to a plain
complex, and then invokes the plain complex's add/mul/etc.
operation.
Solution: add the following to your Complex class:
def __coerce__(self, other):
x = complex.__coerce__(self, other)
if x is NotImplemented:
return x
a, b = x
return Complex(a), Complex(b)
I don't think I want to do anything to fix this, although I
think I'll pass it on to Fred for documentation (not that I
expect him to be in a hurry to fix it either, given the
subtlety of the issues).
In the long run, I think complex should stop using coercion
and start behaving like a "new-style" number like all the
other numeric types. That should fix the second mystery.
Also, in the long run, the sq_repeat and sq_concat slots
should be deprecated and instead sequences should implement
multiply and add operations. Then the funny business in
int_mul could be taken out and the first mystery would
disappear.
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2002-03-18 09:49
Message:
Logged In: YES
user_id=6380
You're right, something's weird. I'll add this to my list.
----------------------------------------------------------------------
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=531355&group_id=5470