2013-07-31 15 views
6

Sto provando a sottoclasse un ndarray numpy ma non riesco a ottenere le operazioni con altri tipi di numpy come array mascherato o matrice. Mi sembra che lo __array_priority__ non venga onorato. Per fare un esempio, ho creato una classe fittizio che imita gli aspetti importanti:La classe derivata dall'array numpy non funziona bene con matrice e matrice mascherata

import numpy as np 

class C(np.ndarray): 

    __array_priority__ = 15.0 

    def __mul__(self, other): 
     print("__mul__") 
     return 42 

    def __rmul__(self, other): 
     print("__rmul__") 
     return 42 

operazioni tra la mia classe e normale lavoro ndarray come previsto:

>>> c1 = C((3, 3)) 
>>> o1 = np.ones((3, 3)) 
>>> print(o1 * c1) 
__mul__ 
42 
>>> print(c1 * o1) 
__rmul__ 
42 

Ma, quando cerco di operare con matrice (o array mascherati) la priorità dell'array non viene rispettata.

>>> m = np.matrix((3, 3)) 
>>> print(c1 * m) 
__mul__ 
42 
>>> print(m * c1) 
Traceback (most recent call last): 
... 
    File "/usr/lib64/python2.7/site-packages/numpy/matrixlib/defmatrix.py", line 330, in __mul__ 
    return N.dot(self, asmatrix(other)) 
ValueError: objects are not aligned 

Mi sembra che il modo ufuncs sono avvolti per array matrice e mascherati non onorare priorità matrice. È questo il caso? C'è una soluzione?

+1

In realtà, viene dato il messaggio di errore perché non sono allineati, in quanto 'np.matrix ((3, 3)) 'non è lo stesso di' np.asmatrix (np.ones ((3, 3))) '. Tuttavia, il problema persiste, tranne che 'm * c1' è quello che non funziona. –

+0

@GustavLarsson Grazie per averlo notato. L'ho risolto e ho aggiunto più informazioni nella motivazione. – Hernan

risposta

2

Una soluzione è quella di creare una sottoclasse np.matrixib.defmatrix.matrix:

class C(np.matrixlib.defmatrix.matrix): 

    __array_priority__ = 15.0 

    def __mul__(self, other): 
     print("__mul__") 
     return 42 

    def __rmul__(self, other): 
     print("__rmul__") 
     return 4 

In questo caso la priorità è anche più alta poi un np.ndarray ei tuoi metodi di moltiplicazione sono sempre chiamati.

Come aggiunto nei commenti, è possibile creare una sottoclasse da più classi in caso di necessità l'interoperabilità:

class C(np.matrixlib.defmatrix.matrix, np.ndarray): 
+0

Funziona bene, ma le mie classi sono meglio descritte da ndarray che da matrix. Inoltre, la mia classe dovrebbe interagire con narray, matrice e darray mascherato. C'è un modo per ottenere questo? – Hernan

+0

Prova ad usare questo approccio e verifica se l'interoperabilità è raggiunta, altrimenti puoi creare sottoclassi da più di una classe, facendo così: 'classe C (np.matrixlib.defmatrix.matrix, np.ndarray):', per esempio. .. –

+0

Ho ridefinito la classe come 'classe C (np.matrixlib.defmatrix.matrix, np.ma.core.MaskedArray, np.ndarray):'. È brutto ma sembra funzionare, ho ancora bisogno di più casi di test. Ora sto cercando di fare lo stesso per una classe che avvolge un array (senza sottoclassi). Ancora una volta, funziona bene quando si accumula da un narray ma non per altro. – Hernan