2015-04-17 216 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更加清晰和靈活。 –