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 _______________________________________________ Numpy-discussion mailing list Numpy-discussion@scipy.org http://projects.scipy.org/mailman/listinfo/numpy-discussion