【问题标题】:Why does int(maxint) give a long, but int(int(maxint)) give an int? Is this a NumPy bug?为什么 int(maxint) 给出一个 long,而 int(int(maxint)) 给出一个 int?这是一个 NumPy 错误吗?
【发布时间】:2017-10-24 15:09:24
【问题描述】:

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

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

为什么调用int 一次给我long,而调用它两次给我int

这是错误还是功能?

【问题讨论】:

  • 在 Ubuntu 14.04 LTS 上使用 Python 2.7.6 和 numpy 1.8.2 以及在 Ubuntu 16.04 LTS 上使用 Python 2.7.12 numpy 1.11.0 也给了我一个 int。
  • 我提到的结果是在 Linux 上。我刚刚在 Windows 上使用 Numpy 1.12.1 进行了测试,我确实重现了你的结果。对于 2147483646,它给出一个 int,但对于 2147483647,它是一个 long
  • 我在使用numpy.int64(9223372036854775807) 的Linux 上遇到同样的错误,它被转换为long,而小于1 的错误被转换为int
  • @AshwiniChaudhary:与问题无关;查看我的编辑。

标签: python python-2.7 numpy int long-integer


【解决方案1】:

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

这种行为是由于 numpy.带有一个参数的int(x) 通过调用PyNumber_Int(x)x 转换为数字。 PyNumber_Int 然后专门接受path for int subclasses,因为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-&gt;ob_type-&gt;tp_as_number-&gt;nb_int,它在numpy/core/src/umath/scalarmath.c.src 中实现。这是为不同类型参数化的代码的位置;这一个用于&lt;typename&gt;_int 方法,用于填充nb_int 方法槽。它有以下一个if

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

这两个运算符都应该是&lt;=。有了&lt;LONG_MINLONG_MAX 都不会通过条件,而是在line 1432 处将它们转换为PyLong

return @func@(x);

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

现在,由于sys.maxint 仍然可以由int 表示,int(long(sys.maxint)) 返回一个int;同样int(sys.maxint + 1) 返回一个long

【讨论】:

    【解决方案2】:

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

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

        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 会生成 int

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      • 2013-06-09
      • 2016-06-28
      相关资源
      最近更新 更多