[Swig-dev] Re: [Python-Dev] Operator overloading inconsistency
(bug or feature?)
Marcelo Matus
mmatus@dinha.acms.arizona.edu
Thu, 08 Aug 2002 08:17:24 -0700
Guido van Rossum wrote:
>>Suppose that a new-style class wants to overload "*" and it
>>defines two methods like this:
>>
>>class Foo(object):
>> def __mul__(self,other):
>> print "__mul__"
>> def __rmul__(self,other):
>> print "__rmul__"
>>
>>Python-2.2.1, if you try this, you get the following behavior:
>>
>>
>>
>>>>>f = Foo()
>>>>>f*1.0
>>>>>
>>>>>
>>__mul__
>>
>>
>>>>>1.0*f
>>>>>
>>>>>
>>__rmul__
>>
>>
>>>>>f*1
>>>>>
>>>>>
>>__mul__
>>
>>
>>>>>1*f
>>>>>
>>>>>
>>__mul__
>>
>>So here is the question: Why does the last statement in this example
>>not invoke __rmul__? In other words, why do "1.0*f" and "1*f" produce
>>different behavior. Is this intentional? Is this documented someplace?
>>Is there a workaround? Or are we just missing something obvious?
>>
>>
>
>Aargh. I *think* this may have to do with the hacks for sequence
>repetition. But I'm not sure. A debug session tracing carefully
>through the code is in order.
>
>--Guido van Rossum (home page: http://www.python.org/~guido/)
>
>
>
I guess the problem arise from here:
intobject.c(340):
========================
static PyObject *
int_mul(PyObject *v, PyObject *w)
{
long a, b;
long longprod; /* a*b in native long arithmetic */
double doubled_longprod; /* (double)longprod */
double doubleprod; /* (double)a * (double)b */
if (!PyInt_Check(v) &&
v->ob_type->tp_as_sequence &&
v->ob_type->tp_as_sequence->sq_repeat) {
/* sequence * int */
a = PyInt_AsLong(w);
return (*v->ob_type->tp_as_sequence->sq_repeat)(v, a);
}
if (!PyInt_Check(w) &&
w->ob_type->tp_as_sequence &&
w->ob_type->tp_as_sequence->sq_repeat) {
/* int * sequence */
a = PyInt_AsLong(v);
return (*w->ob_type->tp_as_sequence->sq_repeat)(w, a);
}
.............
==================
and the facts that:
1.- there is only one 'sq_repeat' method, and not an addittional
'sq_rrepeat' one,
so, n*x and x*n call the same method sq_repeat.
2.- in typeobect.c, sq_repeat is associated with __mul__
line 2775:
SLOT1(slot_sq_repeat, "__mul__", int, "i")
line 3497:
SQSLOT("__mul__", sq_repeat, slot_sq_repeat, wrap_intargfunc,
"x.__mul__(n) <==> x*n"),
3.- the 'object' class by default enable the "tp_as_sequence" attribute,
triggering the call of sq_repeat in the case
1*c
but not in
1.0*c
Marcelo