May 19, 2007 will

Python unions? That's crazy talk!

I don't often say this, but I miss something from C++ that I can't do in Python. What I miss is unions. I know they can be dangerous and aren't supported consistently across compilers, but damn it, they can occasionally be useful.

I'm working on a 4x4 matrix class (for 3D maths) as part of my Game Objects library. It's something I have done several times in C++, where I create a union of a two dimensional array and four Vector4 classes. That way the matrix is conceptually both a grid of numbers and four vectors, which allows for quite elegant code. For example if I have a CMatrix class that stores the transform for a spaceship and I want to move it forward 2 units, I might use code like this.

matSpaceship.vecTranslation += matSpaceship.vecHeading * 2.;

Which is nicely descriptive. I have something similar as part of my Python Matrix44 class; there are descriptive properties that return the appropriate row from the matrix as a tuple. So the equivalent spaceship code would be something like this.

spaceship_transform.translate += Vector3(spaceship_transform.heading) * 2

I find the extra step of having to create a new Vector3 object to be extra noise in the code, but it seems unavoidable. The reason I return an immutable object rather than a Vector3 is because changes to the vector wouldn't have any effect on the parent Matrix. But frankly, it would be nice if they did. I would like to write something like spaceship_transform.translate.y += 1 to move the spaceship along the y axis. I considered getting it working with a proxy object for the matrix rows that caught changes and modified the parent matrix - which I'm sure would work, but it would introduce inefficiency to something that should be fast and lean.

I'm not suggesting having a union construct for Python - heaven forbid! But it does feel like a 'wart' in my Matrix class. And that kind of thing can keep me up at night. :-(

Use Markdown for formatting
*Italic* **Bold** `inline code` Links to [Google](http://www.google.com) > This is a quote > ```python import this ```
your comment will be previewed here
gravatar
Steve Rogers

Have you considered NumPy (http://numpy.scipy.org)? It's ndarray object can have different views and it is well optimized.

# Steve

gravatar
Will

I considered it, but I wanted to give the matrix class a very beginner friendly interface - and I didn't want to introduce an extra dependancy.

It would be fast though, so I may eventualy add a wrapper to a NumPy array that provides my matrix interface.

gravatar
Name

Have you considered using properties? For example, your matrix class could define a .vecHeading property that constructs and returns a new vector.

Or, define your own vector class that can act as a list, and return one of those from the .heading property.

gravatar
Will

I do have properties like that, but they create a copy of the row. So if you modify .heading, it won't change the original matrix. I'd have to do some deep magic to make the changes to the properties feed back to the matrix.

gravatar
Webmechs Press editor
This is five years late and you may have already found the answer…

Wouldn't overriding __attr__ or one of the other special method names accomplish what you're trying to do above? e.g. I have the ff:

 class Pos:
  def __init__(self,x,y):
      self.x=x
      self.y=y
  def __len__(self):
      return 2
  def __getitem__(self,key):
      if key==0: return self.x
      if key==1: return self.y
      if key>1: raise IndexError
  def __setitem__(self,key,value):
      if key==0: self.x=value
      if key==1: self.y=value
      if key>1: raise IndexError
  def __repr__(self):
      return "'%s.Pos(%s,%s)'" % (__name__,self.x,self.y)
  def __str__(self):
      return "(%s,%s)" % (self.x,self.y)

so:

 >>> p = Pos(10,5)
>>> p[0] is p.x
True