2015-04-17 2 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

Я использую 'numpy' 1.9.2 в Windows, и оба сравнения возвращают' 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 просто проверяет, что два типа (я) не эквивалентны, и (б) о том, что первый тип может быть приведен ко второму типу ,

Эта функция также подвергается в API NumPy, как np.can_cast:

3

Это ничего интересного. Python 2 пытается обеспечить последовательные, но бессмысленные результаты сравнения для объектов, которые не определяют, как сравнивать себя друг с другом. Разработчики решили, что это была ошибка, и в Python 3 эти сравнения повысят TypeError.

+0

Второе сравнение делает * not * fail в Python 3, и неверно подразумевать, что оно бессмысленно (как первое сравнение). Это связано с тем, может ли один тип быть отлит другим. (Я добавил ответ, объясняющий это.) –

+0

@ajcr: Huh. Должен признаться, я фактически не проверял документацию, но теперь, когда я посмотрел, я не вижу никакого сравнения для dtypes, документально зафиксированного где-либо.Источник соответствует тому, что вы описываете, но на такое поведение нам разрешено полагаться, или это может измениться без предупреждения? Документировано ли это где угодно? – user2357112

+0

Я также не мог найти документацию, описывающую это использование операторов сравнения, или даже любые обмены в соответствующих списках рассылки. Кажется, это только один из тех уголков библиотеки, который еще не задокументирован. Я не уверен, что разработчики изменят поведение в будущих выпусках, но я, конечно, не видел, чтобы он использовался раньше. Такие функции, как 'can_cast', кажутся намного более четким и гибким способом сравнения dtypes. –

Смежные вопросы