Data encapsulation is one of the three main pillars of object oriented programming, known as PIE (Polymorphism, Inheritance, Encapsulation). Encapsulation refers to providing controlled access to class members via functions. With encapsulation, you can restrict unauthorized access to class members and you can set conditions on the values you want associated with your class.
In this tutorial, we’re going to show you to implement encapsulation in Python.
Why Data Encapsulation is Important
Before we actually show you how to implement data encapsulation in Python, let’s first explain why data encapsulation is important and what issues can occur when you don’t encapsulate your data.
The following script defines a class named
class Product:
def __init__(self, name, price, category):
self.name = name
self.price = price
self.category = category
The script below creates two objects:
prod1 = Product("Table", 500, "Furniture")
prod2 = Product("Computer", 1000, "Electronics")
print(prod1.name, prod1.price, prod1.category)
print(prod2.name, prod2.price, prod2.category)
Output:
Table 500 Furniture
Computer 1000 Electronics
If you allow unrestricted access to member variables, like our
prod1.price = "abcd"
prod2.category = "xyz"
The script below prints the member attributes of the
print(prod1.name, prod1.price, prod1.category)
print(prod2.name, prod2.price, prod2.category)
Output:
Table abcd Furniture
Computer 1000 xyz
What if you want only positive integers to be assigned to the
In Python, access modifiers, getters and setters are used to implement encapsulation. Let’s first check out what access modifiers are in Python.
Code More, Distract Less: Support Our Ad-Free Site
You might have noticed we removed ads from our site - we hope this enhances your learning experience. To help sustain this, please take a look at our Python Developer Kit and our comprehensive cheat sheets. Each purchase directly supports this site, ensuring we can continue to offer you quality, distraction-free tutorials.
Understanding Python Access Modifiers
Access modifiers in Python are used to define the access level for class members. There are three access levels for class members:
- public
- protected
- private
To define a private member, you need to prefix double underscores with a class member, like __name. A private member can only be accessed within the class where it is declared.
A protected member is accessed within a class, by all the child classes and within the same package. To declare a protected member, you need to prefix a single underscore before a variable name, like _name.
Finally, a public member can be accessed everywhere. You don’t need to make any changes to the variable name while defining a public variable.
Let’s see an example. The script below defines a public attribute (name), a protected attribute (_price) and a private attribute (__category).
class Product:
def __init__(self, name, price, category):
self.name = name
self._price = price
self.__category = category
The script below creates an object of our new
prod1 = Product("Table", 500, "Furniture")
Now, let’s attempt to print the values of our name, _price and __category attributes.
print(prod1.name)
print(prod1._price)
print(prod1.__category)
From the output below, you can see that the public and protected members are printed on the console, but the private member can’t be accessed outside the
Output:
Table
500
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-53-d4c45166502a> in <module>
1 print(prod1.name)
2 print(prod1._price)
----> 3 print(prod1.__category)
AttributeError: 'Product' object has no attribute '__category'
Notice that with a private member, once a class is defined, you can still access and edit the attribute directly, like we do in the following example, but you’re not actually changing the value associated with the
prod1 = Product("Table", 500, "Furniture")
prod1.__category = "Vehicle"
print(prod1.__category)
Output:
Vehicle
Now that you understand the concept of access modifiers, let’s show you how to implement encapsulation using getters and setters.
Using Getters and Setters for Encapsulation
Getters and setters are what we call functions that are used to respectively retrieve (get) and assign (set) values to member attributes. Instead of providing direct access to the member attributes, the getter and setter functions are used to provide restricted access to member variables.
The idea of encapsulation in Python is that:
- first you make member variables private and then
- using getters and setters, you specify conditions that must be followed with access member variables.
Let’s see this in action. The script below defines a class
For each of the member attributes, two functions are defined for getting and setting values of these member attributes. For instance the get_name()
and set_name()
methods are defined to get and set the value for our __name attribute.
Similarly, the get_price()
and set_price()
functions are defined as getter and setter, respectively, for the __price attribute. The set_price()
method defines that the value being assigned to the __price attribute should be numeric and a positive value. Similarly, the get_price()
method only returns the value of the __price attribute if it is less or equal to 100.
Finally the set_category()
method defines that the assigned value for the __category attribute must be either Furniture, Electronic, or Mobile.
class Product:
def __init__(self, name, price, category):
self.__name = name
self.__price = price
self.__category = category
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
def get_price(self):
if self.__price > 100:
print("please email us for price")
return
return self.__price
def set_price(self, price):
if type(price) != int and type(price) != float:
print("Price should be a numeric value")
return
if price < 0:
print("Price should be a positive value")
return
self.__price = price
def get_category(self):
return self.__category
def set_category(self, category):
if category not in ["Furniture", "Electronic", "Mobile"]:
print("Category should be Furniture, Electronic, or Mobile")
return
self.__category = category
From the above script, you can see how getters and setters are used to define different conditions for getting and setting values of member attributes.
The following script creates an object of the
prod1 = Product("Table", 50, "Furniture")
Now if you try to directly access the value of the __name attribute, you’ll see an error, like the one below:
prod1.__name
Output:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-140-6fd3364d6636> in <module>
----> 1 prod1.__name
AttributeError: 'Product' object has no attribute '__name'
You can still access the __name attribute but now you have to use the getter function we created, get_name()
.
prod1.get_name()
Output:
'Table'
Similarly, you can set the value of the __name attribute via its setter function as shown below:
prod1.set_name("chair")
prod1.get_name()
Output:
'chair'
Just like we explained earlier, you can’t directly access the __price attribute because it’s private:
prod1.__price
Output:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-143-397f7c9b9d49> in <module>
----> 1 prod1.__price
AttributeError: 'Product' object has no attribute '__price'
Instead, the get_price()
function must be used to get the value of the __price attribute.
prod1.get_price()
Output:
50
Let’s now try to assign -50 as the value for the __price attribute using the set_price()
method.
prod1.set_price(-50)
Since the set_price()
function restricts negative values, you’ll see the following output:
Output:
Price should be a positive value
Similarly, our setter function specifies you can’t assign a non-numeric value to the __price attribute, as we’ll demonstrate here:
prod1.set_price("fifty")
Output:
Price should be a numeric value
Finally, let’s assign a valid value, 200.0, to the __price attribute.
prod1.set_price(200.0)
Now, if you try to get the value of the __price attribute, you’ll see the following message.
prod1.get_price()
Output:
please email us for price
This is because our get_price()
method specifies that if the price is greater than 100, the price isn’t directly returned to the console. The beauty of getters and setters is that you’re able to specify whatever conditions you want on your attributes!
For completeness, we’ll show you that you can’t directly access the __category attribute, either.
prod1.__category
Output:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-149-112d40622343> in <module>
----> 1 prod1.__category
AttributeError: 'Product' object has no attribute '__category'
Instead, the script below calls the get_category()
method to access the value from our __category attribute.
prod1.get_category()
Output:
'Furniture'
Okay, now let’s try to assign a random value to the __category attribute using the set_category()
method.
prod1.set_category("Vehicle")
Since the value assigned is not either Furniture, Electronic, or Mobile, you’ll get the following notification.
Output:
Category should be Furniture, Electronic, or Mobile
Let’s assign a valid value (Furniture, Electronic, or Mobile) to the __category attribute and then retrieve that value from our __category attribute.
prod1.set_category("Electronic")
prod1.get_category()
Output:
'Electronic'
That’s Python encapsulation in a nutshell! It’s really valuable because it lets you both protect and restrict access to the attributes of your classes. For more Python programming tips like this, I hope you’ll subscribe using the form below.
Code More, Distract Less: Support Our Ad-Free Site
You might have noticed we removed ads from our site - we hope this enhances your learning experience. To help sustain this, please take a look at our Python Developer Kit and our comprehensive cheat sheets. Each purchase directly supports this site, ensuring we can continue to offer you quality, distraction-free tutorials.