Подклассы Python numpy.ndarray и массивы нулевого ранга
Я пытаюсь создать подкласс numpy.ndarray
, Это очень просто, и это просто массив с некоторыми дополнительными атрибутами и методами, которые управляют этими атрибутами. По большей части это работает нормально, однако у меня есть проблема при использовании таких сокращений, как np.sum
,
Во-первых, я прочитал подклассы ndarray и массивы нулевого ранга.
Кажется, что когда я создаю подкласс ndarray
он ведет себя по-разному в отношении массива нулевого ранга -> скалярного преобразования.
В этом примере я просто использую простейший производный класс, который на самом деле ничего не делает:
class XArray(np.ndarray):
pass
x = np.eye(2)
y = x.view(type=XArray)
print type(np.sum(x)), type(np.sum(y))
<type 'numpy.float64'> <type '__main__.XArray'>
Первый - скалярный скаляр, второй - массив нулевого ранга моего подкласса. Переопределение __new__
а также __array_finalize__
как задокументировано в руководстве по созданию подклассов массивов, это не меняет этого поведения.
Во-первых, моя проблема: это нарушает объектно-ориентированность. XArray
экземпляры не могут быть заменены ndarray
экземпляры прозрачно, не нарушая много кода.
Я могу это исправить, переопределив __array_wrap__
метод:
class XArray(np.ndarray):
def __array_wrap__(self, obj):
if len(obj.shape)==0:
return obj[()]
else:
return np.ndarray.__array_wrap__(obj)
a = np.sum(np.eye(2).view(XArray))
print type(a)
<type 'numpy.float64'>
Я в порядке с этим, за исключением двух вопросов:
Это правильное место для этого особого случая? Я не могу понять, где происходит это преобразование для обычных массивов numpy, поэтому я не могу сказать, где это должно происходить с моим производным классом.
Достаточно ли этого для работы моего подкласса или у меня будут проблемы с совместимостью? Должен ли я просто отказаться от идеи создания подклассов
ndarray
?
Цель в том, чтобы быть на 100 % совместимым с обычными массивами numpy. Это нормально и ожидается, что некоторые операции потеряют информацию о производном типе и вернут ndarray
Базовый класс. Я в порядке с этим, я просто не могу написать код для работы ndarray
перерыв