Ответ 1
Этот вопрос специфичен для Numpy и Python 2. В Python 3 нет отдельных типов int
и long
.
Поведение происходит из-за ошибки "один за другим" в numpy. int(x)
с одним аргументом преобразует x
в число, вызывая PyNumber_Int(x)
. PyNumber_Int
затем специально использует путь для подклассов int
, поскольку int64
, возвращаемый numpy.int_
, является подклассом int
m = o->ob_type->tp_as_number;
if (m && m->nb_int) { /* This should include subclasses of int */
/* Classic classes always take this branch. */
PyObject *res = m->nb_int(o);
if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
PyErr_Format(PyExc_TypeError,
"__int__ returned non-int (type %.200s)",
res->ob_type->tp_name);
Py_DECREF(res);
return NULL;
}
return res;
}
Теперь для этого кода вызывается a->ob_type->tp_as_number->nb_int
, который реализован в numpy/core/src/umath/scalarmath.c.src. Это место для кода, параметризованного для разных типов; этот для метода <typename>_int
, который используется для заполнения слота метода nb_int
. Он имеет следующий оттуда if
:
if(LONG_MIN < x && x < LONG_MAX)
return PyInt_FromLong(x);
оба оператора должны быть <=
. С <
там ни LONG_MIN
, ни LONG_MAX
не передают условие, и вместо этого они преобразуются в PyLong
в строка 1432:
return @[email protected](x);
с заменой @[email protected]
на PyLong_FromLongLong
в случае int_
. Таким образом, возвращается long(sys.maxint)
.
Теперь, когда sys.maxint
по-прежнему представляется int
, int(long(sys.maxint))
возвращает int
; аналогично int(sys.maxint + 1)
возвращает a long
.