Ответ 1
int.__mul__
- это оболочка слота, а именно PyWrapperDescrObject, а operator.mul
является функцией buit-in.
Я думаю, что противоположная скорость выполнения вызвана этой разницей.
>>> int.__mul__
<slot wrapper '__mul__' of 'int' objects>
>>> operator.mul
<built-in function mul>
Когда мы вызываем PyWrapperDescrObject, вызывается wrapperdescr_call
.
static PyObject *
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
{
Py_ssize_t argc;
PyObject *self, *func, *result;
/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
argc = PyTuple_GET_SIZE(args);
if (argc d_type->tp_name);
return NULL;
}
self = PyTuple_GET_ITEM(args, 0);
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
(PyObject *)(descr->d_type))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.200s' "
"requires a '%.100s' object "
"but received a '%.100s'",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name,
self->ob_type->tp_name);
return NULL;
}
func = PyWrapper_New((PyObject *)descr, self);
if (func == NULL)
return NULL;
args = PyTuple_GetSlice(args, 1, argc);
if (args == NULL) {
Py_DECREF(func);
return NULL;
}
result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(args);
Py_DECREF(func);
return result;
}
Давайте посмотрим, что мы нашли!
func = PyWrapper_New((PyObject *)descr, self);
Создан новый объект PyWrapper. Это значительно замедлит скорость выполнения.
Иногда для создания нового объекта требуется больше времени, чем для запуска простой функции.
Таким образом, не удивительно, что int.__mul__
медленнее, чем operator.mul
.