I am learning getters and setters , what I understand is that they are used so that no one could change the object's attributes directly. In the example
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def get_age(self):
return self._age
def set_age(self, new_age):
if isinstance(new_age, int) & new_age>0 & new_age<120:
self._age = new_age
def get_name(self):
return self._name
def __str__(self):
return 'Person[' + self._name + '] is ' + str(self._age)
p1 = Person("Sandeep", 49)
I created an object p1
where I set the age 49. As I have made a set_age
function so I expect we can change the age of p1
through set_age
only, not through the routine way. But it is not happening, I am able to change the age of p1
through , for example, p1._age = 35
as well. Then, what is the advantage to make set_age
function, if I am still able to access the attributes directly?
I think, I am missing something, please help.
The reason to use a getter and setter, is if you want to do something more complex than just set and attribute with foo.bar
. In your case, set_age
has an
isinstance(new_age, int) & new_age>0 & new_age<120
check, which is not possible to do with a raw attribute. (Side-note: you should use and
instead of &
.)
Yes, someone can still do p1._age = -1
, and then their code won't work, but why would they? It just makes their code not work.
Your get_name
function is less useful than the age
one. It basically makes name
read-only, which might or might not be useful.
When creating setters and getters in Python, it is usual to use the @property
decorator. This means the functions can be called as if they were attributes, so instead of p1.get_name()
you can just do p1.name
. Similarly p1.set_age(3)
becomes p1.age = 3
.
You probably want to use the age setter in __init__
, because then the age of the Person
is validated when it is created.
Here is a version that makes these changes (and a couple of other readability improvements).
class Person:
def __init__(self, name, age):
self._name = name
self.age = age
@property
def age(self):
return self._age
@age.setter
def age(self, new_age):
if isinstance(new_age, int) and 0 < new_age < 120:
self._age = new_age
@property
def name(self):
return self._name
def __str__(self):
return f"Person[{self.name}] is {self.age}"
p1 = Person("Sandeep", 49)