2015-04-17 15 views
5

Grałem z porównywaniem typów danych dwóch różnych tablic, aby wybrać taki, który jest odpowiedni do połączenia tych dwóch. Byłem szczęśliwy, aby dowiedzieć się, że mogę wykonywać operacje porównania, ale w procesie odkryto następujące dziwne zachowanie:Porównanie typu danych NumPy

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

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

może ktoś wyjaśnić, co tu się dzieje? To jest NumPy 1.8.2.

+0

Nawiasem mówiąc, skończyło się na odkrywaniu i używając 'np.find_common_type' ale nadal jestem zainteresowany tym, co dzieje się tutaj. Dzięki! – farenorth

+0

Używam 'numpy' 1.9.2 na Windows, a oba porównania zwracają' Fałsz'. Tak jak w poniższej odpowiedzi, jest to bez znaczenia i zostało usunięte w Pythonie 3. – MattDMo

Odpowiedz

4

Pierwsze porównanie nie ma znaczenia, drugie ma znaczenie:.

Z numpy.int16 > numpy.float32 porównujemy dwie type obiekty:

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

w Pythonie 3 porównanie to nie od razu, ponieważ nie ma zdefiniowane zamawianie type przypadkach. W Pythonie 2 zwracana jest wartość logiczna, ale nie można na niej polegać dla spójności (wraca ona do porównywania adresów pamięci lub innych rzeczy na poziomie implementacji).

Drugie porównanie wykonuje działa w Pythonie 3 i działa konsekwentnie (to samo w Pythonie 2). To dlatego, że jesteśmy teraz porównując dtype instancje:

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

Jaka jest logika tej kolejności?

dtype instancje są uporządkowane zgodnie z tym, czy można rzucać (bezpiecznie) do innego. Jeden typ to mniejszy niż inny, jeśli może być bezpiecznie odlewać do tego typu.

Aby wprowadzić operatorów porównania, spójrz na descriptor.c; konkretnie przy funkcji arraydescr_richcompare.

Oto co < mapy operatorowi:

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

Zasadniczo NumPy tylko sprawdza, że ​​oba typy są (i) nie są równoważne, oraz (ii) że pierwszy typ może być oddane do drugiego typu .

Ta funkcjonalność jest również wystawiony w API NumPy jak np.can_cast:

3

To nic ciekawego. Python 2 próbuje zapewnić spójne, ale bez znaczenia wyniki porównania dla obiektów, które nie definiują sposobu porównywania się ze sobą. Deweloperzy uznali, że to był błąd, a w Pythonie 3 porównania te podniosą TypeError.

+0

Drugie porównanie * nie * zawiedzie w Pythonie 3 i nie jest prawidłowe sugerowanie, że nie ma ono znaczenia (jak pierwsze porównanie). Ma to związek z tym, czy jeden typ może być rzutowany na inny. (Dodałem odpowiedź wyjaśniającą to.) –

+0

@ajcr: Huh. Muszę przyznać, że faktycznie nie sprawdzałem dokumentacji, ale teraz, gdy już spojrzałem, nie widzę żadnego porównania dla dtypes udokumentowanych gdziekolwiek.Źródło pasuje do tego, co opisujesz, ale czy jest to zachowanie, na którym możemy polegać, czy jest to coś, co może ulec zmianie bez powiadomienia? Czy jest to udokumentowane w dowolnym miejscu? – user2357112

+0

Nie mogłem również znaleźć żadnej dokumentacji opisującej to użycie operatorów porównania, ani nawet żadnych wymian na odpowiednich listach mailingowych. Wygląda na to, że jest to jeden z tych zakątków biblioteki, który nie został jeszcze udokumentowany. Nie jestem pewien, czy deweloperzy zmienią zachowanie w przyszłych wydaniach, ale z pewnością nie widziałem, żeby był używany wcześniej. Funkcje takie jak 'can_cast' wydają się znacznie bardziej przejrzystym i elastycznym sposobem porównywania dtypów. –

Powiązane problemy