Image

Image_winnie wrote in Imageru_python

Перегрузка операций

Сейчас пишу расширение, которое ведёт себя как арифметический тип.
Меня удивляет, что питон на питоний код во втором умножении ругается:
class X:
    def __mul__(a, b):
        print a
        print b
        
X() * 2
print '-'
2 * X()
********************
2
-
Traceback (most recent call last):
  File "x.py", line 10, in 
    2 * X()
TypeError: unsupported operand type(s) for *: 'int' and 'instance'


А при определении оператора в сишном коде - не ругается:
static PyObject* TPyPoint2f_op_mul(PyObject *a, PyObject *b);

static void InitOperators()
{
    Point2f_Operators.nb_add = TPyPoint2f_op_add;
    Point2f_Operators.nb_subtract = TPyPoint2f_op_sub;
    Point2f_Operators.nb_multiply = TPyPoint2f_op_mul;

    Point2f_Operators.nb_inplace_add = TPyPoint2f_op_inplace_add;
    Point2f_Operators.nb_inplace_subtract = TPyPoint2f_op_inplace_sub;
    Point2f_Operators.nb_inplace_multiply = TPyPoint2f_op_inplace_mul;

    Point2f_Operators.nb_negative = TPyPoint2f_op_negative;
    Point2f_Operators.nb_positive = TPyPoint2f_op_positive;
}

static void InitType()
{
    Point2fType.tp_name = "chi_math.Point2f";
    Point2fType.tp_basicsize = sizeof(TPyPoint2f);
   
    Point2fType.tp_methods = TPyPoint2f_methods;
    Point2fType.tp_members = TPyPoint2f_members;
    
    Point2fType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES;
    
    Point2fType.tp_as_number = &Point2f_Operators;
}
********************
Зовём из питона:
    assert Point2f(1, 2) * 4 == Point2f(4, 8) #ok
    assert 4 * Point2f(1, 2) == Point2f(4, 8) #ok


В чём тут дело?
updated: Подсказали про питон, я забыл про __rmul__ :(. И внутри сишных исходников:
SLOT1BIN(slot_nb_multiply, nb_multiply, "__mul__", "__rmul__")
#define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, OPSTR, ROPSTR) \