TL;DR
So if you have heavy logic in the @property
function, be aware that it will be running the entire logic each time you access the property. In this case I would suggest using a getter with a setter
Verbose
Another aspect which I don't feel has been explored is that the @property
which is a getter
, could be and most likely will be called multiple times where as the setter
will most likely be called once when you instantiate the object.
IMO, this model should be used if the @property
function is not doing too much heavy lifting. In the example below, we are just concatenating some strings to generate an email address.
class User:
DOMAIN = "boulder.com"
def __init__(self, first_name: str, last_name: str) -> None:
self.first_name = first_name
self.last_name = last_name
@property
def email(self) -> str:
return "{}_{}@{}".format(self.first_name, self.last_name, self.DOMAIN)
But if you are going to add some extended or heavy logic to the function, then I would recommend creating a getter
for it so that it is only run once. For example, lets say we need to check whether the email is unique, this logic would be better served in a getter
other wise you will run the logic to check for uniqueness of the email each time you want to access it.
class User:
DOMAIN = "boulder.com"
def __init__(self, first_name: str, last_name: str) -> None:
self.first_name = first_name
self.last_name = last_name
@property
def email(self) -> str:
return self._email
@email.setter
def email(self) -> None:
proposed_email = "{}_{}@{}".format(self.first_name, self.last_name, self.DOMAIN)
if is_unique_email(proposed_email):
self._email = proposed_email
else:
random_suffix = get_random_suffix()
self._email = "{}_{}_{}@{}".format(
self.first_name, self.last_name, random_suffix, self.DOMAIN
)