Getter and Setter Methods
00:00 Getter and Setter Methods. When you define a class in object-oriented programming, you’ll likely end up with some instance and class attributes. These attributes are just variables that you can access through the instance, the class, or both.
00:16 Attributes hold the internal state of objects. In many cases, you’ll need to access and mutate the state, which involves accessing and mutating the attributes. Typically, you’ll have at least two ways to access and mutate attributes.
00:30 You can either access and mutate the attribute directly or use methods to access and mutate the attribute. If you expose the attributes of a class to your users, then those attributes automatically become part of the class’s public API.
00:46 They’ll be public attributes. This means that your users will directly access and mutate the attributes in their code. Having an attribute that’s part of a class’s API will become a problem if you need to change the internal implementation of the attribute itself.
01:03 A clear example of this issue is when you want to turn a stored attribute into a computed one. A stored attribute will immediately respond to access and mutation operations by just retrieving and storing the data, whereas a computed attribute will run computations before such operations.
01:19 The problem with regular attributes is they can’t have an internal implementation because they are just variables. So changing an attribute’s internal implementation will require converting the attribute into a method, which will probably break your user’s code. Why?
01:34 Because they’ll have to change attribute access and mutation operations into method calls throughout their codebase if they want the code to continue working.
01:45 One solution for this issue is to provide additional methods for manipulating the attributes of your classes. It’s used by languages including Java and C++.
01:54 These methods are commonly known as getter and setter methods, but you may also find them referred to as accessor and mutator methods. Getter and setter methods are quite popular in many object-oriented programming languages, and it’s pretty likely you’ve heard about them already.
02:12 As a rough definition, a getter is a method that allows you to access an attribute in a given class, and a setter is a method that allows you to set or mutate the value of an attribute in a class.
02:24 If an attribute is likely to change its internal implementation, then you should use getter and setter a methods. This pattern also suggests that public attributes should be used only when you’re sure that no one will ever need to attach behavior to them.
02:39
Implementing the getter and setter pattern requires making your attributes non-public and writing getter and setter methods for each attribute. Let’s say you need to write a Label
class with text and font attributes.
02:55 If you were to use getter and setter methods to manage these attributes, then you’d write write code similar to what’s seen on-screen.
03:05
Here, the constructor of Label
takes two arguments, text
and font
. These arguments are stored in the ._text
and ._font
non-public instant attributes, respectively.
03:17 Then you define getter and setter methods for both attributes. Typically, getter methods return the target attribute’s value while setter methods take a new value and assign it to the underlying attribute.
03:44
Note that Python doesn’t have the notion of access modifiers, such as private
, protected
, and public
, to restrict access to attributes and methods in a class.
03:54
In Python, the distinction is between public and non-public class members. If you want to signal that an attribute or method is non-public, then you should use the well-established Python convention of prefixing the name with an underscore (_
). But note that this is just a convention.
04:10 It doesn’t stop you and other programmers from accessing the attributes using dot notation as seen on-screen. However, it is bad practice to violate this convention.
04:23
You can see the Label
class in action on-screen.
04:34
Label
hides its attributes from public access and exposes getter and setter methods instead.
04:43 You can use these methods when you need to access or mutate the class’s attributes, which are non-public and therefore not part of the class API.
04:57
To sum the problem up, think back to the Label
example and imagine that you want to automatically store the label’s text in uppercase letters. Unfortunately, you can’t simply add this behavior to a regular attribute such as .text
.
05:11 You can only add behavior through methods, but converting a public attribute into a method will introduce a breaking change in your API. So what can you do?
05:23 Well, in Python, you’ll most likely use a property as you’ll learn later on. However, programming languages such as Java and C++ don’t support property-like constructs, or their properties aren’t quite like Python properties. Instead, you provide getter and setter methods, which offer a quick way to change the internal implementation of the attributes without changing the public API.
05:45 This is why these languages encourage you to never expose your attributes as part of your public API. Encapsulation is another fundamental topic related to the origin of getter and setter methods. In essence, this principle refers to the bundling of data with the methods that operate on that data. This way, access and mutation operations will be done through methods exclusively.
06:09
The principle also extends to restricting direct access to an object’s attributes, which will prevent exposing implementation details or violating state invariance. To provide Label
with a newly required functionality in Java or C++, you must use getter and setter methods from the beginning.
06:26
But how can you apply the getter and setter pattern to solve the problem in Python? Take a look at the updated version of Label
seen on-screen.
06:50
In this version of Label
, you provide getter and setter methods for the label’s text. The attribute holding the text is non-public because it has a leading underscore in its name, and the setter method does the input transformation, converting the text into uppercase letters.
07:11
Now you can use the Label
class as seen on-screen.
07:31 You’ve successfully added the required behavior to the label’s text attribute. Now, your setter method has a true goal instead of just assigning a new value to the target attribute.
07:45 Even though the getter and setter pattern is quite common in other programming languages, that is not the case in Python. Adding getter and setter methods to your classes can considerably increase the number of lines in your code.
07:56 Getters and setters also follow a repetitive pattern that will require extra time to complete. This can be error-prone and tedious. You’ll also find that the immediate functionality gained from all this additional code is often zero.
08:12
All of this sounds like something that Python developers wouldn’t want to do in their code. In Python, you’d probably write the Label
class as seen in this REPL session.
08:29
Here, .text
and .font
are public attributes, and they’re exposed as part of the class’s API. This means that your users can and will change their value whenever they like,
08:42 creating an initial value
08:48
and then later on in the code modifying it to a new value. Exposing attributes like .text
and .font
is common practice in Python, so your users will directly access and mutate this kind of attribute in their code.
09:05 Making your attributes public, as in this example, is a common practice in Python. In these cases, switching to getters and setters will introduce breaking changes.
09:14 So how do you deal with situations that require adding behavior to your attributes? The Pythonic way to do this is to replace attributes with properties, and that’s what you’ll see in the next section of the course.
Become a Member to join the conversation.