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