[Numpy-discussion] numpy.matrix subclassing

Aronne Merrelli aronne.merrelli at gmail.com
Tue Oct 25 11:24:59 EDT 2011


On Mon, Oct 24, 2011 at 5:54 PM, David Voong <voong.david at gmail.com> wrote:

> Hi guys,
>
> I have a question regarding subclassing of the numpy.matrix class.
>
> I read through the wiki page,
> http://docs.scipy.org/doc/numpy/user/basics.subclassing.html
>
> and tried to subclass numpy.matrix, I find that if I override the
> __finalize_array__ method I have problems using the sum method and get the
> following error,
>
>
> Traceback (most recent call last):
>   File "test.py", line 61, in <module>
>     print (a * b).sum()
>   File "/afs/
> cern.ch/user/d/dvoong/programs/lib/python2.6/site-packages/numpy/matrixlib/defmatrix.py",
> line 435, in sum
>     return N.ndarray.sum(self, axis, dtype, out)._align(axis)
>   File "/afs/
> cern.ch/user/d/dvoong/programs/lib/python2.6/site-packages/numpy/matrixlib/defmatrix.py",
> line 370, in _align
>     return self[0,0]
>   File "/afs/
> cern.ch/user/d/dvoong/programs/lib/python2.6/site-packages/numpy/matrixlib/defmatrix.py",
> line 305, in __getitem__
>     out = N.ndarray.__getitem__(self, index)
> IndexError: 0-d arrays can only use a single () or a list of newaxes (and a
> single ...) as an index
>
>
>
Hi,

Thanks for asking this - I'm also trying to subclass np.matrix and running
into similar problems; I never generally need to sum my vectors so this
wasn't a problem I had noticed thus far.

Anyway, for np.matrix, there are definitely particular issues beyond what is
described on the array subclassing wiki. I think I have a workaround, based
on struggling with my own subclass. This is really a hack since I'm not sure
how some parts of matrix actually work, so if someone has a better solution
please speak up!

You didn't give details on the actual subclass, but I can recreate the error
with the following minimal example (testing with Numpy 1.6.1 inside EPD
7.1):

class MatSubClass1(np.matrix):
    def __new__(cls, input_array):
        obj = np.asarray(input_array).view(cls)
        return obj
    def __array_finalize__(self, obj):
        pass
    def __array_wrap__(self, out_arr, context=None):
        return np.ndarray.__array_wrap__(self, out_arr, context)

In [2]: m1 = MatSubClass1( [[2,0],[1,1]] )
In [3]: m1.sum()
...
IndexError: 0-d arrays can only use a single () or a list of newaxes (and a
single ...) as an index


The problem is that __array_finalize__ of the matrix class that needs to get
called, to preserve dimensions (matrix should always have 2 dimensions). You
can't just add the matrix __array_finalize__ because the initial call
happens when you create the object, in which case obj is a ndarray object,
not a matrix. So, check to see obj is a matrix first before calling it. In
addition, there is some undocumented _getitem attribute inside matrix, and I
do not know what it does. If you just set that attribute during __new__, you
get something that seems to work:

class MatSubClass2(np.matrix):
    def __new__(cls, input_array):
        obj = np.asarray(input_array).view(cls)
        obj._getitem = False
        return obj
    def __array_finalize__(self, obj):
        if isinstance(obj, np.matrix):
            np.matrix.__array_finalize__(self, obj)
    def __array_wrap__(self, out_arr, context=None):
        return np.ndarray.__array_wrap__(self, out_arr, context)

In [4]: m2 = MatSubClass2( [[2,0],[1,1]] )

In [5]: m2.sum(), m2.sum(0), m2.sum(1)
Out[5]: (4, matrix([[3, 1]]), matrix([[2], [2]]))


HTH,
Aronne
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20111025/3924c769/attachment.html>


More information about the NumPy-Discussion mailing list