为什么 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_MIN
和 LONG_MAX
之间的整数,此代码生成 int
。对于值为 LONG_MAX
的整数,它返回到 return @func@(x);
的情况,其中 @func@
由模板引擎从 PyLongFrom*
系列中的适当函数替换。
因此,在值为 LONG_MAX
的 NumPy int 上调用 int
会产生一个 long
,但由于结果可以表示为一个 int,因此在结果再次产生 int
.
此问题特定于 Numpy 和 Python 2。在 Python 3 中没有单独的 int
和 long
类型。
该行为的发生是由于 numpy 中的一个差一错误。 int(x)
带有一个参数,通过调用 PyNumber_Int(x)
. PyNumber_Int
then specifically takes the path for int
subclasses 将 x
转换为数字,因为 numpy.int_
返回的 int64
是 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. 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_MIN
和 LONG_MAX
均未通过条件,而是在 line 1432:
处转换为 PyLong
return @func@(x);
@func@
在 int_
的情况下被 PyLong_FromLongLong
取代。因此,返回 long(sys.maxint)
。
现在,由于 sys.maxint
仍然可以表示为 int
、int(long(sys.maxint))
returns 和 int
;同样 int(sys.maxint + 1)
returns a long
.
非常不言自明(我在 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_MIN
和 LONG_MAX
之间的整数,此代码生成 int
。对于值为 LONG_MAX
的整数,它返回到 return @func@(x);
的情况,其中 @func@
由模板引擎从 PyLongFrom*
系列中的适当函数替换。
因此,在值为 LONG_MAX
的 NumPy int 上调用 int
会产生一个 long
,但由于结果可以表示为一个 int,因此在结果再次产生 int
.
此问题特定于 Numpy 和 Python 2。在 Python 3 中没有单独的 int
和 long
类型。
该行为的发生是由于 numpy 中的一个差一错误。 int(x)
带有一个参数,通过调用 PyNumber_Int(x)
. PyNumber_Int
then specifically takes the path for int
subclasses 将 x
转换为数字,因为 numpy.int_
返回的 int64
是 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. 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_MIN
和 LONG_MAX
均未通过条件,而是在 line 1432:
PyLong
return @func@(x);
@func@
在 int_
的情况下被 PyLong_FromLongLong
取代。因此,返回 long(sys.maxint)
。
现在,由于 sys.maxint
仍然可以表示为 int
、int(long(sys.maxint))
returns 和 int
;同样 int(sys.maxint + 1)
returns a long
.