2015-04-17 18 views
5

Stavo giocando con il confronto dei tipi di dati di due diversi array per sceglierne uno adatto alla combinazione dei due. Sono stato felice di scoprire che ho potuto effettuare operazioni di confronto, ma nel processo scoperto i seguenti strano comportamento:Confronto del tipo di dati NumPy

In [1]: numpy.int16 > numpy.float32 
Out[1]: True 

In [2]: numpy.dtype('int16') > numpy.dtype('float32') 
Out[2]: False 

Qualcuno può spiegare cosa sta succedendo qui? Questo è NumPy 1.8.2.

+0

Per inciso, ho finito per scoprire e utilizzare 'np.find_common_type' ma sono ancora interessati a quello che stava succedendo qui. Grazie! – farenorth

+0

Sto usando 'numpy' 1.9.2 su Windows, ed entrambi i confronti restituiscono' False'. Come nella risposta seguente, questo è privo di significato ed è stato rimosso in Python 3. – MattDMo

risposta

4

Il primo confronto non è significativo, il secondo è significativo.

Con numpy.int16 > numpy.float32 stiamo confrontando due type oggetti:

>>> type(numpy.int16) 
type 
>>> numpy.int16 > numpy.float32 # I'm using Python 3 
TypeError: unorderable types: type() > type() 

In Python 3 questo paragone non regge immediatamente poiché non v'è nessun ordinamento definito per type istanze. In Python 2, viene restituito un valore booleano ma non può essere invocato per coerenza (ricade sul confronto tra gli indirizzi di memoria o altre cose a livello di implementazione).

Il secondo confronto fa funziona in Python 3 e funziona in modo coerente (lo stesso in Python 2). Questo perché ora stiamo confrontando dtype casi:

>>> 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 

Qual è la logica che sta dietro questo ordinamento?

dtype Le istanze sono ordinate a seconda che si possa lanciare (in sicurezza) a un'altra. Un tipo è inferiore a un altro se può essere cast sicuro per quel tipo.

Per l'implementazione degli operatori di confronto, vedere descriptor.c; in particolare nella funzione arraydescr_richcompare.

Ecco ciò che il < mappe operatore a:

switch (cmp_op) { 
case Py_LT: 
     if (!PyArray_EquivTypes(self, new) && PyArray_CanCastTo(self, new)) { 
      result = Py_True; 
     } 
     else { 
      result = Py_False; 
     } 
     break; 

In sostanza, NumPy solo controlla che i due tipi sono (i) non equivalenti, e (ii) che il primo tipo possono essere lanciate al secondo tipo .

Questa funzionalità è inoltre esposto nelle API NumPy come np.can_cast:

3

Non è niente di interessante. Python 2 tenta di fornire risultati di confronto coerenti ma privi di significato per oggetti che non definiscono come confrontarsi l'uno con l'altro. Gli sviluppatori hanno deciso che si trattava di un errore e in Python 3 questi confronti aumenteranno il numero TypeError.

+0

Il secondo confronto non * fallisce in Python 3 e non è corretto implicare che non ha senso (come il primo confronto è). Riguarda se un tipo può essere lanciato su un altro. (Ho aggiunto una risposta per spiegarlo.) –

+0

@ajcr: Huh. Devo ammettere che in realtà non ho controllato la documentazione, ma ora che ho guardato, non vedo alcun confronto per i dtype documentati ovunque.La fonte corrisponde a ciò che descrivi, ma è questo comportamento su cui ci basiamo o è qualcosa che potrebbe cambiare senza preavviso? È documentato da qualche parte? – user2357112

+0

Inoltre, non sono riuscito a trovare alcuna documentazione che descrivesse questo uso di operatori di confronto o persino eventuali scambi sulle mailing list pertinenti. Sembra che sia solo uno di quegli angoli della biblioteca che non è ancora stato documentato. Non sono sicuro che gli sviluppatori cambieranno il comportamento nelle versioni future, ma sicuramente non l'ho mai visto molto prima. Funzioni come 'can_cast' sembrano un modo molto più chiaro e flessibile per confrontare i dtypes. –