tags:

views:

101

answers:

3

I have a the following class:


class Vector(object):
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z

    def _getx(self):
        return self._x
    def _setx(self, value):
        self._x = float(value)
    x = property(_getx, _setx)

    def _gety(self):
        return self._y
    def _sety(self, value):
        self._y = float(value)
    y = property(_gety, _sety)

    def _getz(self):
        return self._z
    def _setz(self, value):
        self._z = float(value)
    z = property(_getz, _setz)

The three getters and setters are all identical except for the object property they are modifying (x, y, z). Is there a way that I can write one get and one set and then pass the variable to modify so that I don't repeat myself?

A: 

Not tested, but this should work:

def force_float(name):
    def get(self):
        return getattr(self, name)
    def set(self, x):
        setattr(self, name, float(x))
    return property(get, set)

class Vector(object):
    x = force_float("_x")
    y = force_float("_y")
    # etc
John Millikin
+6  A: 

Sure, make a custom descriptor as per the concepts clearly explained in this doc:

class JonProperty(object):
    def __init__(self, name):
        self.name = name

    def __get__(self, obj, objtype):
        return getattr(obj, self.name)

    def __set__(self, obj, val):
        setattr(obj, self.name, float(val))

and then just use it:

class Vector(object):
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z
    x = JonProperty('_x')
    y = JonProperty('_y')
    z = JonProperty('_z')
Alex Martelli
Worked great! thanks.
Jon
Always glad to help! BTW, remember to accept an answer (use the "checkmark" icon under the number giving the answer's up/down votes) once you've verified it's a right solution to your problem -- that's fundamental stack overflow etiquette.
Alex Martelli
+1  A: 

Why not just write this?

class Vector(object):
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z

If your getters and setters are a carryover in practice from something like Java, then DO NOT WRITE THEM. Just expose the attributes x, y, and z. You can change them to properties later if necessary, and, unlike Java (which would require some kind of recompile), all of the client code will still work just fine.

On the theme of getters and setters in Python, the general consensus as I understand it is "don't write 'em til you need 'em." Only write setters and getters if they actually add value to your program (like protecting an internal data structure, perhaps). Otherwise, leave them out, and spend your time doing actual productive coding.

Paul McGuire
Originally I wanted a mechanism to gaurantee that x, y, and z would always be a float, in case a user entered an int or string. However,I started thinking about about this some more and agree with you. I am going to continue with the "we're all adults" python attitude and leave it to the class user to make sure a float is stored.The knowledge I learned about defining decorators was worth it though.
Jon