为什么 int(maxint) 给出的是 long,而 int(int(maxint)) 给出的是 int?这是 NumPy 错误吗?

Why does int(maxint) give a long, but int(int(maxint)) give an int? Is this a NumPy bug?

非常不言自明(我在 Windows):

>>> import sys, numpy
>>> a = numpy.int_(sys.maxint)
>>> int(a).__class__
<type 'long'>
>>> int(int(a)).__class__
<type 'int'>

为什么调用 int 一次得到 long,而调用两次得到 int

这是错误还是功能?

正如(现已删除的)其他答案中所建议的那样,这似乎是一个错误,因为不正确地使用了 < 而不是 <=,但它不是来自代码在另一个答案中引用。该代码是打印逻辑的一部分,这里不涉及。

我相信处理 int 调用 NumPy 标量的代码是从 numpy/core/src/umath/scalarmath.c.src 中的 template 生成的,有符号整数数据类型的相关部分是

    if(LONG_MIN < x && x < LONG_MAX)
        return PyInt_FromLong(x);
#endif
    return @func@(x);

对于严格介于 LONG_MINLONG_MAX 之间的整数,此代码生成 int。对于值为 LONG_MAX 的整数,它返回到 return @func@(x); 的情况,其中 @func@ 由模板引擎从 PyLongFrom* 系列中的适当函数替换。

因此,在值为 LONG_MAX 的 NumPy int 上调用 int 会产生一个 long,但由于结果可以表示为一个 int,因此在结果再次产生 int.

此问题特定于 Numpy 和 Python 2。在 Python 3 中没有单独的 intlong 类型。

该行为的发生是由于 numpy 中的一个差一错误。 int(x) 带有一个参数,通过调用 PyNumber_Int(x). PyNumber_Int then specifically takes the path for int subclassesx 转换为数字,因为 numpy.int_ 返回的 int64int 的子类:

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. 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 方法槽中实现。它有以下关闭一个 if 那里:

if(LONG_MIN < x && x < LONG_MAX)
    return PyInt_FromLong(x);

两个运算符都应该是 <=。在 < 的情况下,LONG_MINLONG_MAX 均未通过条件,而是在 line 1432:

处转换为 PyLong
return @func@(x);

@func@int_ 的情况下被 PyLong_FromLongLong 取代。因此,返回 long(sys.maxint)

现在,由于 sys.maxint 仍然可以表示为 intint(long(sys.maxint)) returns 和 int;同样 int(sys.maxint + 1) returns a long.