Best-Practice for organizing properties in a python class [closed]

  softwareengineering

When using properties in a Python class, you have a lot of boilerplate code. Is there a best practice to hide the code for the getters and setters?

I know about @dataclass, but the problem is mainly with classes that are not data classes, where you have to scroll through the boilerplate code to get to the actual functions.

One idea would be to create the properties on a base class and then inherit from it to implement the functions. But I am not sure if this is clean code or if there are better design patterns for it.

Example:

class Circle:
    def __init__(self, x, y, r):
        self._x = x
        self._y = y
        self._r = r

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @property
    def y(self):
        return self._y

    @x.setter
    def y(self, value):
        self._y = value

    @property
    def r(self):
        return self._r

    # No setter for r. The circle can be moved but not resized.

    def draw(self):
        # Draw the circle using x, y, r

13

DISCLAIMER

I do not want to present this as a best practice. I don’t even want to encourage this kind of thing. For most projects, this is going to create a lot of confusion and it’s definitely not what I would consider idiomatic. To be clear, you almost surely don’t actually want to do this.

END DISCLAIMER

Having said that, if you are truly in a situation where you have a large amount of boilerplate around properties and you can’t use dataclasses or normal attributes, here’s one technique that could be used instead. I feel like there’s probably different design approach to address this more properly but it’s impossible to say without more detail.

In a nutshell, properties can be implemented programmatically. The decorators are essentially short hand for the property built-in method.

def prop(name, readonly=False):
    def g(obj):
        return getattr(obj, f"_{name}")
    
    def s(obj, value):
        return setattr(obj, f"_{name}", value)
    
    if readonly:
        return property(g)
    else:
        return property(g, s)


class Circle:
    def __init__(self, x, y, r):
        self._x = x
        self._y = y
        self._r = r

    x = prop('x')
    y = prop('y')
    r = prop('r', True)

    def draw(self):
        print(f"Circle: ({self.x}, {self.y}), {self.r}")


circle = Circle(5, 5, 10)

circle.x = 50
circle.y = 20

circle.draw()

circle.r = 30

The only time I could really think something like this would be justified is if you a very large number of setters and getters where the only thing that changes in the body of each method is the name of the property or something where you can write a prop method as above which can implement many (dozens, hundreds) of such properties.

But most likely, people will hate you for doing things like this. I expect to get some downvotes for even mentioning it. But your question piqued my curiosity, and I learned a few things in the process, so I feel obligated to give you my findings in return.

LEAVE A COMMENT