2015-04-17 157 views
5

我在比较两个不同数组的数据类型,选择一个适合组合这两个数组的数据类型。我很高兴地发现,我可以执行比较操作,但在这个过程中发现以下奇怪现象:NumPy数据类型比较

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

顺便说一句,我结束了发现和使用'np.find_common_type'但我在什么怎么回事仍然有兴趣。谢谢! – farenorth

+0

我在Windows上使用'numpy' 1.9.2,并且两个比较都返回'False'。正如在下面的答案中,这是没有意义的,并且已经在Python 3中被删除。 – MattDMo

回答

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

3

这没什么意思。 Python 2试图为不定义如何彼此比较自己的对象提供一致但无意义的比较结果。开发人员认为这是一个错误,在Python 3中,这些比较将会提高TypeError

+0

第二个比较在Python 3中确实*不*失败,并且暗示它没有意义(如第一次比较)是不正确的。这是关于一种类型是否可以转换为另一种类型。 (我已经添加了一个解释这个的答案。) –

+0

@ajcr:嗯。我必须承认我没有真正检查文档,但现在我看了,我没有看到任何地方记录的dtypes的比较。源代码与您所描述的内容相匹配,但是这种行为是我们可以依赖的吗?还是可能在没有通知的情况下发生变化?它记录在任何地方吗? – user2357112

+0

我也找不到任何文档描述比较运算符的这种用法,甚至找不到相关邮件列表上的任何交换。看起来它只是图书馆尚未记录的那些角落之一。我不确定开发者是否会在未来的版本中改变这种行为,但是我之前从未看到过它的用处。像'can_cast'这样的函数看起来比dtypes更加清晰和灵活。 –