我只花了半个小时来研究statsmodels中的一个错误' SARIMAX功能,我终于可以追溯到numpy.int32失败的类型检查int的事实。
>>> import numpy as np
>>> foo = np.int32(3)
>>> isinstance(foo, int)
False
如果没有明确的类型转换,有没有办法绕过这种问题? 正确的代码是否应该测试类型而不检查变量是否可以安全地转换为类型?
编辑:我的问题由一个帐户回答,说明了这种行为的原因是什么技术限制或设计决定,以及如何python处理纯python的int
和numpy {{1}可能会出现{或int32
种类型。
答案 0 :(得分:4)
为什么应该 numpy.int32
来自int
? int
是一个特定的类。它是表示整数的一种方式。这并不意味着每个表示整数的类都应该来自int
。 numpy.int32
具有不同的语义和不同的方法 - 例如,它具有像0维数组一样运行所需的大部分功能 - 并且继承自int
对于实现{{1}并不是特别有用}。
在Python 2的某些版本(仅限Windows?)上,numpy.int32
实际上将从numpy.int32
下降(在这些版本上也是32位),但我相信这个设计决定可以追溯到int
执行环绕式算术(如int
而不是在溢出时向numpy.int32
提升,以及long
不存在的时间。那时候这是一个更合理的决定。
至于operator.index
numpy.int32
如何处理int
,numbers.Integral
做了一些好工作,但实施依赖于人们明确地register
使用{ {1}},人们通常不认为这样做。在引入numbers.Integral
6年后,NumPy在2014之前未添加register
次来电。像SymPy这样的类似的库仍然没有调用。
我发现numbers.Integral
是更好的检查:
operator.index
try:
real_int = operator.index(some_intlike_thing)
except TypeError:
# Not intlike.
do_something_about_that()
是一个类似于类的类必须实现的钩子,以使其实例可用作序列索引。这是一个比operator.index
更严格的检查,它会接受int(x)
和3.5
。如果缺少这个钩子会产生一个具体的,容易引起注意的影响,那么它比'3'
支持更有可能存在。
答案 1 :(得分:3)
__mro__
列出了类的继承堆栈:
np.int32.__mro__
Out[30]:
(numpy.int32,
numpy.signedinteger,
numpy.integer,
numpy.number,
numpy.generic,
object)
int.__mro__
Out[31]: (int, object)
对于基本数组:
x=np.array([1,2,3])
x.dtype
Out[33]: dtype('int32')
此堆栈上的 isinstance
个类返回True:
isinstance(x[0], np.int32)
Out[37]: True
isinstance(x[0], np.number)
Out[38]: True
int
不在此堆栈中:
isinstance(x[0], int)
Out[39]: False
isinstance(x[0], object)
Out[40]: True
item
从numpy
包装器中提取值:
isinstance(x[0].item(), int)
Out[41]: True
@kazemakase建议使用numbers
模块:
isinstance(x[0], numbers.Integral)
Out[47]: True