Сравнение типов данных NumPy

99
11

Я играл с сопоставлением типов данных двух разных массивов, чтобы выбрать тот, который подходит для объединения двух. Я был рад узнать, что я мог выполнять операции сравнения, но в процессе обнаружил следующее странное поведение:


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

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


Может ли кто-нибудь объяснить, что здесь происходит? Это NumPy 1.8.2.

спросил(а) 2015-04-18T00:55:00+03:00 5 лет, 5 месяцев назад
1
Решение
89

Первое сравнение не имеет смысла, второе имеет смысл.


С 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) что первый тип может быть передан второму типу.


Эта функциональность также отображается в API NumPy как np.can_cast:


>>> np.can_cast('int32', '|S10')
False
>>> np.can_cast('int32', '|S11')
True

ответил(а) 2015-04-18T17:00:00+03:00 5 лет, 5 месяцев назад
81

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

ответил(а) 2015-04-18T00:57:00+03:00 5 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема