Методы подклассов numpy: numpy возвращают ndarray вместо типа с подклассами? - PullRequest
0 голосов
/ 11 апреля 2020

Мне удалось создать подкласс numpy:

class myary(np.ndarray):
def __new__(cls, arg1, arg2) : 
   .....
        obj = super(myary, cls).__new__(cls, shape=(arg1,), dtype=np.int)
        ....
        return obj

, это работает, но проблема в том, что я применяю numpy функции (например, np.concatenate (), np.stack () .. .. et c) вывод ndarray вместо myary. Я реализовал __array_wrap__, поэтому np.sort, np.add ... работают, но не тот, который я упомянул выше.

def __array_wrap__(self, out_arr, context=None):
    return super(self.__class__, self).__array_wrap__(out_arr, context)

Как заставить все методы numpy возвращать то, что я передаю как вход.

1 Ответ

1 голос
/ 24 апреля 2020

Похоже, что адаптация class.__array_function__(func, types, args, **kwargs) - это путь к go начиная с версии 1.16 NumPy в соответствии с этим справочным документом . Это описание имеет полезный (хотя и редкий) пример того, как реализовать numpy.concatenate и numpy.broadcast_to, что облегчило мне его реализацию! В самом простом (и даже более редком), вот как обработать numpy .concatenate и вернуть экземпляр вашего класса:

    import numpy as np

    class MyClass:
        def __array_function__(self, func, types, args, kwargs):
            if func == np.concatenate:
                < do stuff here for concatenating your class >
                return < result of stuff done of type MyClass>
            else:
                return NotImplemented

В качестве примечания, когда я реализовал np.concatenate, я был сбит с толку относительно того, как numpy знал, как вызывать мой метод, когда я предоставлял список своих подклассов в качестве ввода (вместо экземпляра моего подкласса). Я нашел это полезным - этот метод вызывается всякий раз, когда вызывается функция массива numpy, и решает, использовать ли вашу реализацию следующим образом (обратите внимание на важность возврата NotImplemented, если вы не обрабатываете данную функцию):

  1. NumPy будет собирать реализации __array_function__ со всех указанных входов и вызывать их по порядку: подклассы перед суперклассами, а в противном случае слева направо. Обратите внимание, что в некоторых крайних случаях, включающих подклассы, это немного отличается от текущего поведения Python.
  2. Реализации __array_function__ указывают, что они могут обрабатывать операцию, возвращая любое значение, отличное от NotImplemented.
  3. Если все __array_function__ методы вернут NotImplemented, NumPy повысит TypeError.
...