When and how to use the builtin function property() in python

Viewed 36336

It appears to me that except for a little syntactic sugar, property() does nothing good.

Sure, it's nice to be able to write a.b=2 instead of a.setB(2), but hiding the fact that a.b=2 isn't a simple assignment looks like a recipe for trouble, either because some unexpected result can happen, such as a.b=2 actually causes a.b to be 1. Or an exception is raised. Or a performance problem. Or just being confusing.

Can you give me a concrete example for a good usage of it? (using it to patch problematic code doesn't count ;-)

8 Answers

It is useful when you try to replace inheritance with delegation in refactoring. The following is a toy example. Stack was a subclass in Vector.

class Vector:
    def __init__(self, data):
        self.data = data

    @staticmethod
    def get_model_with_dict():
        return Vector([0, 1])


class Stack:
    def __init__(self):
        self.model = Vector.get_model_with_dict()
        self.data = self.model.data


class NewStack:
    def __init__(self):
        self.model = Vector.get_model_with_dict()

    @property
    def data(self):
        return self.model.data

    @data.setter
    def data(self, value):
        self.model.data = value


if __name__ == '__main__':
    c = Stack()
    print(f'init: {c.data}') #init: [0, 1]

    c.data = [0, 1, 2, 3]
    print(f'data in model: {c.model.data} vs data in controller: {c.data}') 
    #data in model: [0, 1] vs data in controller: [0, 1, 2, 3]

    c_n = NewStack()
    c_n.data = [0, 1, 2, 3]
    print(f'data in model: {c_n.model.data} vs data in controller: {c_n.data}') 
    #data in model: [0, 1, 2, 3] vs data in controller: [0, 1, 2, 3]

Note if you do use directly access instead of property, the self.model.data does not equal self.data, which is out of our expectation.

You can take codes before __name__=='__main__' as a library.

Related