为什么 numpy.int32 不被识别为 int 类型

Neu*_*eck 8 python types numpy

我只花了半个小时研究 statsmodels 的 SARIMAX 功能中的一个错误,我最终可以追溯到 numpy.int32 未能对 int 进行类型检查这一事实。

>>> import numpy as np
>>> foo = np.int32(3)
>>> isinstance(foo, int)
False
Run Code Online (Sandbox Code Playgroud)

有没有办法在没有显式类型转换的情况下规避这种问题?正确的代码是否应该测试类型而不检查变量是否可以安全地转换为类型?

编辑:我的问题是通过说明导致此行为的技术限制或设计决策以及如何以 python 方式处理可能出现纯 pythonint和 numpyint32int64类型的情况来回答的。

use*_*ica 8

为什么 numpy.int32下降intint是一个特定的类。它是表示整数的一种方式。这并不意味着每个表示整数的类都应该从int. numpy.int32具有不同的语义和不同的方法 - 例如,它具有像 0 维数组一样操作所需的大部分功能 - 并且继承 fromint对于实现numpy.int32.

在 Python 2 的某些版本(仅限 Windows?)上,numpy.int32实际上会从int(在这些版本上也是 32 位的),但我相信这个设计决定可以追溯到int执行环绕算术numpy.int32而不是提升到long溢出的时候,什么operator.index时候不存在。这在当时是一个更合理的决定。

至于如何处理numpy.int32like intnumbers.Integral做的还不错,但是实现依赖于人们明确地使用 来处理register他们的类numbers.Integral,而人们通常不认为这样做。NumPyregister直到2014年才添加调用,numbers.Integral也就是在引入6 年后。SymPy 之类的类似库仍然没有调用。

我发现operator.index这是一个更好的检查:

try:
    real_int = operator.index(some_intlike_thing)
except TypeError:
    # Not intlike.
    do_something_about_that()
Run Code Online (Sandbox Code Playgroud)

operator.index是一个类似 int 的类必须实现的钩子,以使其实例可用作序列索引。这是一个比 更严格的检查int(x),它会接受3.5'3'。由于如果缺少此挂钩会产生具体的、容易引起注意的影响,因此它比numbers.Integral支撑更有可能存在。


hpa*_*ulj 7

__mro__ 列出类的继承堆栈:

np.int32.__mro__
Out[30]: 
(numpy.int32,
 numpy.signedinteger,
 numpy.integer,
 numpy.number,
 numpy.generic,
 object)

int.__mro__
Out[31]: (int, object)
Run Code Online (Sandbox Code Playgroud)

对于基本数组:

x=np.array([1,2,3])    
x.dtype
Out[33]: dtype('int32')
Run Code Online (Sandbox Code Playgroud)

isinstance 此堆栈上的类返回 True:

isinstance(x[0], np.int32)
Out[37]: True    
isinstance(x[0], np.number)
Out[38]: True    
Run Code Online (Sandbox Code Playgroud)

int 不在此堆栈中:

isinstance(x[0], int)
Out[39]: False    
isinstance(x[0], object)
Out[40]: True
Run Code Online (Sandbox Code Playgroud)

item从其numpy包装器中提取一个值:

isinstance(x[0].item(), int)
Out[41]: True
Run Code Online (Sandbox Code Playgroud)

@kazemakase 建议使用该numbers模块:

isinstance(x[0], numbers.Integral)
Out[47]: True
Run Code Online (Sandbox Code Playgroud)

编辑

isinstance接受一组类,因此我们可以通过一个测试同时处理intnumpy情况:

In [259]: isinstance(x[0], (int,np.integer))                                                           
Out[259]: True
In [260]: isinstance(x[0].item(), (int,np.integer))                                                    
Out[260]: True
Run Code Online (Sandbox Code Playgroud)