[Python-Dev] Bug in PyNumber_InPlacePower implementation?

Guido van Rossum guido@python.org
Tue, 28 May 2002 21:00:11 -0400


> I was looking at the implementation of PyNumber_InPlacePower last
> night, and something about it struck me as odd. It starts off:
> 
> 	if (HASINPLACE(v) && v->ob_type->tp_as_number &&
> 	    v->ob_type->tp_as_number->nb_inplace_power != NULL) {
> 		return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");
> 
> Now, looking at ternary_op, it appears that under some
> circumstances this could call the nb_inplace_power slot
> of the second or third argument before trying the first
> one:
> 
> 	if (slotv) {
> 		if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
> 			x = slotw(v, w, z);
> 
> i.e. if the 2nd argument is a subtype of the 1st, and it
> has an nb_inplace_power method, it will be called first.
> 
> This looks wrong to me. Surely only the *first* argument
> should be checked for an inplace method when doing an
> inplace operation? That's the way it seems to be for
> all the other inplace operations. Is this a bug?

This is exactly the same as what binary_op1() does.  I added this
twist intentionally because of a use case where a subclass of a
numeric type wants to override a binary (or ternary) operator defined
by the base class.  If the subclass wasn't tried first, it would never
be able to override the case where a base class instance is the left
operand, because the base class implementation is generally happy to
accept a subclass instance as the right operand.  (I admit that a
comment explaining this would have been handy. :-)

Do you have a use case where this does the wrong thing, or is this
just a theoretical musing?

--Guido van Rossum (home page: http://www.python.org/~guido/)