chanwcom
chanwcom

Reputation: 4680

The usage of @property and @value.setter

I am somewhat confused about @property and @value.setter property in Python. I studied the following website, and I think I understand the basic concept.

https://www.programiz.com/python-programming/property

After studying this, I made the following sample program, and it works fine. But in the following case, even if I remove the @property and @value.setter, it still works fine. Then, what might be the difference when we add @property and @value.setter above two methods?

#!/usr/bin/python

class TreeNode(object):
    def __init__(self):
        self._value = None
        self._left_node = None
        self._right_node = None

    @property
    def value(self):
        return self._value

   @value.setter
    def value(self, value):
        self._value = value

def main():
    tree_node = TreeNode()
    tree_node.value = 3 

    print (tree_node.value)


if __name__ == '__main__':
    main()

Upvotes: 1

Views: 859

Answers (2)

merlyn
merlyn

Reputation: 2361

When you aren't using @property and @value.setter, tree_node.value = 3 just replaces the value attribute which you had previously defined as a function. Since your property is just hiding the real variable, there isn't any noticeable difference in the two pieces of code. That will change if the @property function is actually doing some work.

For instance, you might want to automatically change the set value to smallest even number greater than the given value:

class TreeNode(object):
    def __init__(self):
        self._value = None
        self._left_node = None
        self._right_node = None

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        if value % 2 == 1:
            self._value = value + 1
        else:
            self._value = value

def main():
    tree_node = TreeNode()
    tree_node.value = 3

    print (tree_node.value)


if __name__ == '__main__':
    main()

Or maybe you want two different properties which are always related to each other.

class TreeNode(object):
    def __init__(self):
        self._value = 0
        self._left_node = None
        self._right_node = None

    @property
    def value(self):
        return self._value

    @property
    def value2(self):
        return self._value * 2

    @value2.setter
    def value2(self, value):
        self._value = value // 2

    @value.setter
    def value(self, value):
        self._value = value

def main():
    tree_node = TreeNode()
    tree_node.value = 3

    print (tree_node.value)
    print (tree_node.value2)


if __name__ == '__main__':
    main()

The two setter functions will make sure that the values are always in sync. Removing the decorators in any of the above examples will break their functionality.

The goal of the @property and @value.setter decorators is to allow special semantics every time you access or set a value while maintaining the elegance of regular attributes.

Upvotes: 4

Uku Loskit
Uku Loskit

Reputation: 42050

The difference is that you if you remove @property, you cannot do the following (well, you can, but it would the reference to the function, rather than the return value):

print(tree_node.value)

because value would then be a regular method, which would have to be called like this:

print(tree_node.value())

Upvotes: 1

Related Questions