[Numpy-discussion] subclassing matrix

Colin J. Williams cjw@sympatico...
Thu Jan 10 09:03:43 CST 2008


Basilisk96 wrote:
> Hello folks,
> 
> In the course of a project that involved heavy use of geometry and
> linear algebra, I found it useful to create a Vector subclass of
> numpy.matrix (represented as a column vector in my case).

Why not consider a matrix with a shape 
of (1, n) as a row vector and
one with (n, 1) as a column vector?

Then you can simply write A * u or u.T * A.

Does this not meet the need?

You could add methods isRowVector and 
isColumnVector to the Matrix class.

Colin W.
> 
> I'd like to hear comments about my use of this "class promotion"
> statement in __new__:
>     ret.__class__ = cls
> 
> It seems to me that it is hackish to just change an instance's class
> on the fly, so perhaps someone could clue me in on a better practice.
> Here is my reason for doing this:
> Many applications of this code involve operations between instances of
> numpy.matrix and instances of Vector, such as applying a linear-
> operator matrix on a vector. If I omit that "class promotion"
> statement, then the results of such operations cannot be instantiated
> as Vector types:
>     >>> from vector import Vector
>     >>> import numpy
>     >>> u = Vector('1 2 3')
>     >>> A = numpy.matrix('2 0 0; 0 2 0; 0 0 2')
>     >>> p = Vector(A * u)
>     >>> p.__class__
>     <class 'numpy.core.defmatrix.matrix'>
> 
> This is undesirable because the calculation result loses the custom
> Vector methods and attributes that I want to use. However, if I use
> that "class promotion" statement, the p.__class__ lookup returns what
> I want:
>     >>> p.__class__
>     <class 'vector.Vector'>
> 
> Is there a better way to achieve that?
> 
> Here is the partial subclass code:
> #---------- vector.py
> import numpy as _N
> import math as _M
> #default tolerance for equality tests
> TOL_EQ = 1e-6
> #default format for pretty-printing Vector instances
> FMT_VECTOR_DEFAULT = "%+.5f"
> 
> class Vector(_N.matrix):
>     """
>     2D/3D vector class that supports numpy matrix operations and more.
> 
>     Examples:
>         u = Vector([1,2,3])
>         v = Vector('3 4 5')
>         w = Vector([1, 2])
>     """
>     def __new__(cls, data="0. 0. 0.", dtype=_N.float64):
>         """
>         Subclass instance constructor.
> 
>             If data is not specified, a zero Vector is constructed.
>             The constructor always returns a Vector instance.
>             The instance gets a customizable Format attribute, which
> controls the printing precision.
>         """
>         ret = super(Vector, cls).__new__(cls, data, dtype=dtype)
>         #promote the instance to cls type.
>         ret.__class__ = cls
>         assert ret.size in (2, 3), 'Vector must have either two or
> three components'
>         if ret.shape[0] == 1:
>             ret = ret.T
>         assert ret.shape == (ret.shape[0], 1), 'could not express
> Vector as a Mx1 matrix'
>         if ret.shape[0] == 2:
>             ret = _N.vstack((ret, 0.))
>         ret.Format = FMT_VECTOR_DEFAULT
>         return ret
> 
>     def __str__(self):
>         fmt = getattr(self, "Format", FMT_VECTOR_DEFAULT)
>         fmt = ', '.join([fmt]*3)
>         return ''.join(["(", fmt, ")"]) % (self.X, self.Y, self.Z)
> 
>     def __repr__(self):
>         fmt = ', '.join(['%s']*3)
>         return ''.join(["%s([", fmt, "])"]) %
> (self.__class__.__name__, self.X, self.Y, self.Z)
> 
>     #### the remaining methods are Vector-specific math operations,
> including the X,Y,Z properties...
> 
> 
> Cheers,
> -Basilisk96



More information about the Numpy-discussion mailing list