Property decorator is a handy solution when you want to expose internal attributes to downstream users. It is basically the pythonic way of creating the getter and setter functions. In my opinion, utilising property decorator would bring two essential benefits.
I’d like to quickly walk through a toy script created to illustrate the benefits. Here we have a vehicle class including three attributes, num_of_wheels, is_new and num_of_backup_wheels. It also has a couple of property interfaces accessing attributes and a property setter for is_new. Finally there is a function named drive().
class Vehicle():
def __init__(self):
self._num_of_wheels = 4 # how many wheels a vehicle has excluding backup wheels
self.__is_new = True # whether or not a vehicle is new
self._num_of_backup_wheels = 1 # how many backup wheels a vehicle has
@property
def is_new(self):
return self.__is_new
@property
def num_of_wheels_excluding_backup(self):
return self._num_of_wheels
@property
def num_of_wheels_including_backup(self):
return self.num_of_wheels_excluding_backup + self._num_of_backup_wheels
def drive(self):
'''
Drive a car and stop, the car is no longer new now.
'''
print('driving')
print('...')
self.__is_new = False
print('stopping')
v = Vehicle()
print('brand new car', v.is_new)
print('num of wheels', v.num_of_wheels_excluding_backup)
print('num of wheels including backup wheels', v.num_of_wheels_including_backup)
v.drive()
print('brand new vehicle', v.is_new)
# OUTPUT:
# brand new car True
# num of wheels 4
# num of wheels including backup wheels 5
# driving
# ...
# stopping
# brand new vehicle False
Benefits
Improve on maintainability
It wouldn’t break the code if later the implementation of a certain attribute requires a change. Imagine we want to modify the visibility of an attribute by changing it to a private attribute from a protected attribute, with the help of property decorator, it would only require someone to make a change on the property interface.
Improve on readability and expressiveness
Sometimes directly access an attribute would makes the code obscure, it would be nice to add an additional layer to express the underlying logic. For example, it is redundant to have an attribute to track how many wheels a vehicle including backups but it would be still useful to provide this information as a property derived from other attributes.