Automatically setting getter, setter and deleter in python

Viewed 4521

Ok I've been reading about using the @property decorator in Python rather than specific methods for getting, setting and deleting. Some example code is shown below.

class Person(object):

    def __init__(self):

        self._firstName = None
        self._lastName = None
        self._age = None

    @property
    def firstName(self): return self._firstName
    @firstName.setter
    def firstName(self, val): self._firstName = val
    @firstName.deleter
    def firstName(self): del self._firstName

    @property
    def lastName(self): return self._lastName
    @lastName.setter
    def lastName(self, val): self._lastName = val
    @lastName.deleter
    def lastName(self): del self._lastName

    @property
    def age(self): return self._age
    @age.setter
    def age(self, val): self._age = val
    @age.deleter
    def age(self): del self._age

Peter = Person()

Peter.firstName = 'Peter'
Peter.lastName = 'Smith'
Peter.age = 21

print ' '.join([Peter.firstName, Peter.lastName])

As you can see, the majority of the code in the example is devoted to defining the methods.

My question is whether there is a way to automatically assign the getter, setter and deleter for each of my variables? In my actual code I have a lot more variables and it seems like a lot of repetitive code setting each method.

I realise that for simple cases it may not strictly be necessary however I'd prefer to code the methods in now in case I ever decide to increase the complexity of the class.

4 Answers

1. Helper function for defining read/write properties in a Python class:

class PropertyHelperDemo:
    '''Demonstrates a property definition helper function'''

    def prop_helper(k: str):
        def _get(self): return self.__dict__.__getitem__(k)
        def _set(self, v): self.__dict__.__setitem__(k, v)
        def _del(self): self.__dict__.__delitem__(k)
        return property(_get, _set, _del)

    X: float = prop_helper('X')
    Y: float = prop_helper('Y')
    Z: float = prop_helper('Z')
    # etc...

    def __init__(self, X: float, Y: float, Z: float):
        super(PropertyHelperDemo, self).__init__()
        (self.X, self.Y, self.Z) = (X, Y, Z)

    # for read-only properties, the built-in technique remains sleek enough already
    @property
    def Total(self) -> float:
        return self.X + self.Y + self.Z

2. Runtime usage:

obj = PropertyHelperDemo(3.0, 4.0, 5.0)

print(obj.Total)                # ―► "12.0"

obj.X = obj.Y = obj.Z = 2.0     # set properties

print(obj.Total)                # ―► "6.0"

print(obj.X ** 3.0)             # get a property ―► "8.0"

del obj.X                       # delete a property
try: print(obj.X)
except: print('nope')           # it's gone ―► "nope"
Related