PDA

View Full Version : Python per instance properties?




Analog Kid
Jan 31, 2012, 05:21 PM
Kinda new to Python programming, so bear with me here if I'm asking something obvious. I've done a cursory web search on the topic and can't find an answer, which may just mean I'm searching for the wrong thing...

Is it possible to define properties on a per-instance basis? For example, I'd like to define a position class that can be created in either cartesian or spherical coordinates. In the cartesian case, I'd store (x,y,z) and calculate (r,az,el) on the fly. In the spherical case, I'd store (r,az,el) and calculate (x,y,z) on the fly.

One way to do this, obviously, is class hierarchy-- create a Position class, then Spherical and Cartesian subclasses.

Where this leads to problems is in defining Pose. Pose is sort of a directed position-- it is both a position and an orientation. As such, I'd like it to subclass Position, but I don't want to have to create both a CartesianPose and SphericalPose. I could instead wrap a position and orientation, but then I need a whole slew of property definitions that do nothing but expose the enclosed Position and Orientation attributes.

What I would like to do is this:


def __init__(self,a=0,b=0,c=0,format='cartesian'):
if(format=='cartesian'):
self.x=a
self.y=b
self.z=c
self.r=property(getR,setR)
self.az=property(getAz,setAz)
self.el=property(getEl,setEl)
elif(format=='spherical'):
self.r=a
self.az=b
self.el=c
self.x=property(getX,setX)
self.y=property(getY,setY)
self.z=property(getZ,setZ)
else:
#add other formats or raise exception


I may not have that quite right, but you get the idea. It doesn't work, of course, because I need to set:
self.__cls__.x=property(...)

Which works, as long as every Position everywhere follows the same format, because I've now tweaked the class for everyone. That kind of defeats the purpose.

Is there a way to do this at the instance level? I'm sure there's a hundred ways of working around this-- I'm implementing one now-- but ideally I'd like to be able to do something like this without putting if/else in every getter:


a=Position(1,2,3,format='cartesian')
print(a.x)
print(a.az)

b=Position(5,pi/4,0,format='spherical')
print(b.x)
print(b.az)