ELI5: Python @property and setter

For this ELI5 I’m gonna go over the @property and setter decorators. In my objects tutorial I mentioned that you can access and alter the content of attributes directly, but this is not always ideal. In other words, these allow you to create “getter” and “setter” methods that are common in other programming languages.

@property a.k.a python getter

First we’ll go over the @property decorator, which allows us to define a “getter” method. By a “getter” I mean a method that gets the value of a property. I’ll start by dumping some code down and explain it line by line. This is going to be an object that handles “time” in hours and minutes.

class Time:
    def __init__(self, hour, minute):
        self._hour = hour
        self._minute = minute

    @property
    def hour(self):
        return self._hour

    @property
    def minute(self):
        return self._minute

So, first thing I’ll explain is the init method. You’ll see here that the attributes begin with an underscore (_) character. This is common practice in python to designate that the attribute is “private”, which means it shouldn’t be accessed by users directly. It doesn’t actually restrict anything though, it’s more of a polite suggestion to users.

Now, for the two @property decorated functions. There are very simple getters, all they do is return the values. What @property does specifically though is it allows you to call these methods without including brackets, let me show you what I mean:

- sampleTime = Time(12, 34)
- sampleTime.hour
12

As you can see, I was able to get the _hour value by typing .hour. You might be wondering why you would bother using this though – it isn’t actually doing anything differently than if we just use self.hour and self.minute in the init right? Well, the main answer is that it’ll gives you access to setters.

Python setter

A setter is simply a method for setting the value of an attribute. These are incredibly useful as it allows you to introduce sanity checking and other additional steps when a user changes an attribute in the object. Here is some sample code showing a setter for the minute attribute:

class Time:
    def __init__(self, hour, minute):
        self._hour = hour
        self._minute = minute

    @property
    def hour(self):
        return self._hour

    @property
    def minute(self):
        return self._minute

    @minute.setter
    def minute(self, value):
        if value < 60:
            self._minute = value
        else:
            raise ValueError

So, let’s jump right down to line 14. Here I name my method @minute.setter, this only works if there is a method named “minute” decorated by an @property already. This code will then check if the value the user is entering is less than 60 and if it isn’t it will throw a ValueError. This means that if a user tries to set the minute of the time to an invalid value it won’t let them.

So, there you have it, a quick intro to @property and how you can use it to create a setter for your python objects. if you want to practice, try adding a getter and setter for “second” and a setter for “hour” in the code above.

The next ELI5 (and final for a while) will be on subclassing. Stay tuned!

This entry was posted in ELI5, Python, tutorial and tagged , . Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.