Managing Attributes in Your Classes
00:00 Managing Attributes in Your Classes. When you define a class in an object-oriented programming language, you’ll probably end up with some instance and class attributes. In other words, you’ll end up with variables that are accessible through the instance, class, or even both, depending on the language. Attributes represent or hold the internal state of a given object, which you’ll often need to access and mutate.
00:28 Typically, you have at least two ways to manage an attribute. Either you can access and mutate the attribute directly, or you can use methods. Methods are functions attached to a given class.
00:39 They provide the behaviors and actions that an object can perform with its internal data and attributes. If you expose your attributes to the user, then they become part of the public API of your classes.
00:53 Your user will access and mutate them directly in their code. The problem comes when you need to change the internal implementation of a given attribute.
01:05
Let’s say you’re working on a Circle
class. The initial implementation has a single attribute called .radius
. You finish coding the class and make it available to your end users.
01:17
They start using Circle
in their code to create projects and applications. Now suppose that you have an important user that comes to you with a new requirement. They don’t want Circle
to store the radius any longer.
01:30
They need a public .diameter
attribute. At this point, removing .radius
to start using .diameter
would break the code of some of your end users. You need to manage this situation in a way other than removing .radius
.
01:46 Programming languages such as Java and C++ encourage you to never expose your attributes to avoid this kind of problem. Instead, you should provide getter and setter methods, also known as accessors and mutators, respectively.
02:01 These methods offer a way to change the internal implementation of your attributes without changing your public API. Note that getter and setter methods are often considered an anti-pattern and a signal of poor object-oriented design.
02:16 The main argument behind this proposition is that these methods break encapsulation. They allow you to access and mutate the components of your objects. In the end, these languages need getter and setter methods because they don’t provide a suitable way to change the internal implementation of an attribute if a given requirement changes. Changing the internal implementation would require an API modification, which can break your end users’ code.
02:45 Technically, there’s nothing that stops you from using getter and setter methods in Python. On-screen, you can see how this approach would look.
03:01
Here, you create Point
with two non-public attributes, ._x
and ._y
, to hold the Cartesian coordinates of the point at hand. To access and mutate the value of either ._x
or ._y
, you can use the corresponding getter and setter methods.
03:18
First, you create the .get()
and .set()
methods for ._x
03:43
Save this code into point.py
and you’ll be able to import the class into your interactive shell.
03:52
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 Python, the distinction is between public and non-public class members.
04:06
If you want to signal that a given attribute or method is non-public, then you have to use the well-known Python convention of prefixing the name with an underscore (_
). That’s the reason behind the naming of the attributes ._x
and ._y
. Note that this is just a convention.
04:23 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:36
On-screen, you can see how you can work with the Point
class in your code. First, you import the Point
class,
04:46
and then you create an instance of it with ._x
and ._y
values.
04:52
With .get_x()
and .get_y()
, you can access the current values of ._x
and ._y
. You can use the setter method to store a new value in the corresponding manage attribute and confirm that it’s changed.
05:10 You can also confirm that Python doesn’t restrict access to non-public attributes.
05:22
Even though the code you’ve just seen uses the Python coding style, it doesn’t look Pythonic. The getter and setter methods don’t perform any further processing with ._x
and ._y
.
05:33
You can rewrite Point
in a more concise and Pythonic way.
06:05 This code uncovers a fundamental principle. Exposing attributes to the end user is normal and common in Python. You don’t need to clutter your classes with getter and setter methods all the time, and that sounds good.
06:21 It does raise the question though, how can you handle requirement changes that would seem to involve API changes? Unlike Java and C++, Python provides handy tools that allow you to change the underlying implementation of your attributes without changing your public API. The most popular approach is to turn your attributes into properties.
06:44 Properties represent an intermediate functionality between a plain attribute, or field, and a method. In other words, they allow you to create methods that behave like attributes. With properties, you can change how you compute the target attribute whenever you need to do so.
07:04
For example, you can turn both .x
and .y
into properties. With this change, you can continue accessing them as attributes. You’ll also have an underlying method holding .x
and .y
that will allow you to modify their internal implementation and perform actions on them right before your users access and mutate them.
07:26 Note that properties aren’t exclusive to Python. Languages such as JavaScript, C#, Kotlin, and others also provide tools and techniques for creating properties as class members.
07:38 The main advantage of Python properties is that they allow you to expose your attributes as part of your public API. If you ever need to change the underlying implementation, then you can turn the attribute into a property at any time without much pain.
07:53 In the next section of the course, you’ll start working with properties in Python.
Become a Member to join the conversation.