Reputation: 4680
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
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
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