我正在玩比较两个不同数组的数据类型,以选择一个适合两者的组合。我很高兴发现我可以执行比较操作,但在此过程中发现了以下奇怪的行为:
In [1]: numpy.int16 > numpy.float32
Out[1]: True
In [2]: numpy.dtype('int16') > numpy.dtype('float32')
Out[2]: False
任何人都可以解释这里发生了什么吗?这是NumPy 1.8.2。
答案 0 :(得分:4)
第一个比较没有意义,第二个 有意义。
使用numpy.int16 > numpy.float32
我们正在比较两个type
个对象:
>>> type(numpy.int16)
type
>>> numpy.int16 > numpy.float32 # I'm using Python 3
TypeError: unorderable types: type() > type()
在Python 3中,此比较立即失败,因为type
个实例没有定义的排序。在Python 2中,返回一个布尔值,但不能依赖它来保持一致性(它可以追溯到比较内存地址或其他实现级别的东西)。
第二个比较 在Python 3中工作,并且它一致地工作(在Python 2中也是如此)。这是因为我们现在正在比较dtype
个实例:
>>> type(numpy.dtype('int16'))
numpy.dtype
>>> numpy.dtype('int16') > numpy.dtype('float32')
False
>>> numpy.dtype('int32') < numpy.dtype('|S10')
False
>>> numpy.dtype('int32') < numpy.dtype('|S11')
True
这种排序背后的逻辑是什么?
dtype
实例根据是否可以(安全地)转换为另一个实例进行排序。一种类型小于另一种类型,如果它可以安全地投射到该类型。
要实现比较运算符,请查看descriptor.c;特别是在arraydescr_richcompare
函数。
以下是<
运算符映射到的内容:
switch (cmp_op) {
case Py_LT:
if (!PyArray_EquivTypes(self, new) && PyArray_CanCastTo(self, new)) {
result = Py_True;
}
else {
result = Py_False;
}
break;
基本上,NumPy只检查两种类型是否(i)不等效,以及(ii)第一种类型可以转换为第二种类型。
此功能也在NumPy API中公开为np.can_cast
:
>>> np.can_cast('int32', '|S10')
False
>>> np.can_cast('int32', '|S11')
True
答案 1 :(得分:3)
没什么好玩的。 Python 2试图为没有定义如何相互比较的对象提供一致但无意义的比较结果。开发人员认为这是一个错误,在Python 3中,这些比较将引发TypeError
。