We don't use getter and setter methods in Python. Instead we make properties.
Properties allow us to customize what happens when you access an attribute and what happens when you assign to an attribute.
How can you customize what happens when you assign to a specific attribute on a Python class?
Here we have a class called
class Person: def __init__(self, name, location): self.name = name self.location = location
Person objects have a
name attribute and a
>>> trey = Person("Trey", "San Diego") >>> trey.name 'Trey' >>> trey.location 'San Diego'
We want to make it so that whenever we assign to the
location attribute all previous values of the
location attribute would be stored somewhere.
>>> trey.location = "Portland"
We'd like to make a
past_locations attribute which would show us all previous values for
location on a specific
In many programming languages, like Java, the solution to this problem is getter methods and setter methods.
So instead of having a
location attribute, we would have a private attribute.
Python doesn't have private attributes, but sometimes we put an underscore (
_) before an attribute name to note that it's private by convention.
Here's an updated version of our
Person class with a getter and setter method and a private (by convention)
class Person: def __init__(self, name, location): self.name = name self.past_locations =  self.set_location(location) def get_location(self): return self._location def set_location(self, location): self._location = location self.past_locations.append(location)
On this new class, instead of accessing
location directly (which doesn't work anymore) we would call the
>>> trey = Person("Trey", "San Diego") >>> trey.get_location() 'San Diego'
And to set a location we'd call the
>>> trey.set_location("Portland") >>> trey.get_location() 'Portland'
The benefit of getter and setter methods is that we can hook into these methods, putting any code we'd like inside them.
For example in our
set_location method, we're appending to the
def set_location(self, location): self._location = location self.past_locations.append(location)
past_locations attribute now shows all locations we've ever set for this
>>> trey.past_locations ['San Diego', 'Portland']
In Python, we don't tend to use getter and setter methods.
We don't have a
get_name, and a
set_name, and a
get_location, and a
set_location for every single attribute.
Instead, we tend to just assign the attributes and read from attributes as we like.
But in this particular situation (where we have an attribute and we'd like to change how it works) we're kind of stuck. We need some way to hook into the assignment of that attribute. Fortunately, in Python, there is a way to do this: we can use a property.
Here's our modified
Person class with properties:
class Person: def __init__(self, name, location): self.name = name self.past_locations =  self.location = location @property def location(self): return self._location @location.setter def location(self, location): self._location = location self.past_locations.append(location)
Properties allow us to hook into the getting of an attribute.
>>> trey = Person("Trey", "San Diego") >>> trey.location 'San Diego'
When we access the
location attribute now, under the hood it's actually accessing the
But properties also allow us to customize what happens when we assign to a specific attribute.
By default, if we assign to a property we'll get an error. But in our case, we don't get an error:
>>> trey.location = "Portland" >>> trey.location 'Portland'
It works because we've implemented a setter for our property:
@location.setter def location(self, location): self._location = location self.past_locations.append(location)
As you can see, the syntax for property setters is a little weird. So rather than memorizing the syntax, you can just look it up when you need it.
The syntax for property setters is a little bit weird, so I don't recommend memorizing it (just look it up when/if you need it).
The property setter syntax starts with the name or our property (
location) followed by
We use that as a decorator to decorate a
location method (named the same as our property):
@location.setter def location(self, location): ...
We accept an argument which represents whatever is assigned to this property (on the right-hand side of the equals sign during assignment).
We're then storing that actual value on
_location, and every time our
location changes, we're appending each value to our
self._location = location self.past_locations.append(location)
So when we access the
past_locations list, both of our locations are reflected:
>>> trey.past_locations ['San Diego', 'Portland']
Any time the
past_locations will be updated.
Notice that even in our initializer, we're assigning to
location (rather than
def __init__(self, name, location): self.name = name self.past_locations =  self.location = location
That's the reason "San Diego" is the first value in this
past_locations list: when we assigned to the
location attribute in our initializer it called our property setter.
In fact, every time
location is assigned to, the setter will be called for this property.
If you would like to customize what happens when you assign to a specific attribute on your class in Python, you can use a property with a setter.
Hello friendly web visitor! 👋
This page is part of Python Morsels, an online Python skill-building service.
The best way to learn is by doing. In the case of Python that means writing Python code. If you'd like to improve your Python skills every week, try out Python Morsels by entering your email below to create an account.
Python Morsels topics pages are free and the first month's worth of exercises is free as well. You don't need to enter payment details to sign up.
You can find explanations of many other Python topics by signing up below.