Skip to main content

Getting started with classes in Python Part 7: getters and setters

james.derrick@ansys.com | 01.21.2025

Once you're writing code for other users to use, you run into a simple problem: users generally don't know the module as well as whoever wrote it (you). In this case, you want your users to have a good time and get good use out of your code, so how do you tackle this? There are the obvious ways like 'write good documentation', and 'provide many examples and tutorials' and whilst all these are good answers to the problem there is something a bit more fundamental you can do. You can write your code in such a way that users can't use it wrong.

We've already looked at one of the ways to handle this with private and super-private naming but another way is through the use of 'setters' and 'getters'.

What is a "setter"/"getter"?

A "setter" is the method on a class that "sets" a property. Similarly a "getter" "gets" the property. Typically these are called something like make = car.get_make() and car.set_make('VW'). In other languages you, as the user, can't simply edit a class property like you can in Python, so these make a lot more sense. However, what you can do in Python is use the @property decorator.

How to use @property

Let's consider the HatchBack example from Part 1, but this time we will call make make_stored and create a method called make with the 'property decorator applied to it that returns the make_stored property.

from dataclasses import dataclass


@dataclass
class HatchBack:
    make_stored: str
    model: str
    weight: float

    @property
    def make(self):
        return self.make_stored


car = HatchBack('Skoda', 'Fabia', 1200.)
print(car.make)

This script returns 'Skoda' but if we know try to set the make property, by running car.make = 'VW', we can't!

In [12]: car.make = 'VW'
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[12], line 1
----> 1 car.make = 'VW'

AttributeError: can't set attribute 'make'

The property decorator effectively turns a method into a 'getter' and blocks the user from setting the property (unless a setter is defined, which we'll get to). A common pattern is to make the property on the class itself private and make the @property the same but public, which hides the "real" property and makes it look like it can't be changed. Pretty neat!

from dataclasses import dataclass


@dataclass
class HatchBack:
    _make: str
    model: str
    weight: float

    @property
    def make(self):
        return self._make


car = HatchBack('Skoda', 'Fabia', 1200.)
print(car.make)

This also adds a lot of potential to do more interesting things like adding code into the getter. For example, if your class needs to fetch a lot of data from a server to calculate the value a property takes, you can put that fetching code in the getter. That way, the data is loaded only on demand, i.e. it is only fetched and loaded when the method is called and NOT when the class is instantiated. When you're creating a lot of instances of a class that each contain a lot of data this can be very beneficial.

How to make a setter?

You could just leave it there; perhaps your property doesn't need to be affected by the user. However, if it does then you need to build a setter. This requires a new decorator. This one will be the name of your getter method, dot, "setter", e.g. @make.setter. It must also have a parameter besides self for whatever is being set to it. I always call it value.

from dataclasses import dataclass


@dataclass
class HatchBack:
    _make: str
    model: str
    weight: float

    @property
    def make(self):
        return self._make
    
    @make.setter
    def make(self, value: str):
        self._make = value


car = HatchBack('Skoda', 'Fabia', 1200.)
car.make = 'VW'
print(car.make)

Once again you can add all sorts of code in here, including type validation as well as any other checks and balances you might find useful.

That's how to build getters and setters into your classes!

For a complete look at the articles in this series, have a look at this overview page: Getting started with classes in Python