Pretty self-explanatory (I'm on Windows):
>>> import sys, numpy
>>> a = numpy.int_(sys.maxint)
>>> int(a).__class__
<type 'long'>
>>> int(int(a)).__class__
<type 'int'>
Why does calling int once give me a long, whereas calling it twice gives me an int?
Is this a bug or a feature?
In Python3, int has no max limit. Python2 has two integer types, int and long , but Python3 has only int . int in Python3 is equivalent to long in Python2, and there is no max limit.
These represent numbers in the range -2147483648 through 2147483647. (The range may be larger on machines with a larger natural word size, but not smaller.)
This question is specific to Numpy and Python 2. In Python 3 there are no separate int and long types.
The behaviour happens due to an off-by-one error in numpy. int(x) with one argument converts x to number by calling PyNumber_Int(x). PyNumber_Int then specifically takes the path for int subclasses, as int64 returned by numpy.int_ is a subclass of 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;
}
Now, for this code calls a->ob_type->tp_as_number->nb_int, which is implemented in numpy/core/src/umath/scalarmath.c.src. This is the location for code that is parametrized for different types; this one for <typename>_int method that is used to fill the nb_int method slot. It has the following off-by one if there:
if(LONG_MIN < x && x < LONG_MAX)
return PyInt_FromLong(x);
both operators should be <= instead. With < there, neither LONG_MIN nor LONG_MAX pass the condition and they're instead are converted into a PyLong at line 1432:
return @func@(x);
with @func@ being replaced by PyLong_FromLongLong in the case of int_. Thus, long(sys.maxint) is returned.
Now, as the sys.maxint is still representable by int, int(long(sys.maxint)) returns an int; likewise int(sys.maxint + 1) returns a long.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With