Home

 › 

Articles

 › 

Encapsulation In Python: What You Need To Know

How to Install Pip on Windows

Encapsulation In Python: What You Need To Know

Whenever working with object-oriented programming (OOP) language, encapsulation is a very common goal. The concept is part of the key principle of these languages, known as data hiding. Together with inheritance, abstraction, and polymorphism, these fundamental concepts aim to make OOP languages efficient, reusable, and easier to understand.

As such, they’re used very widely in most programming settings, and if you’re a budding developer, it would be well worth it to familiarize yourself with these ideas. Without further ado, let’s get into what encapsulation’s all about and how it’s implemented in Python.

What Is Encapsulation, And Why Is It Important?

In simple terms, encapsulation describes the notion of “hiding” data that work together as one unit of code. In this scenario, hiding refers to preventing access to the internal workings of a program from the code outside of it.

The data within can only be accessed from a well-defined interface, leading to a more intuitive experience and data protection. Accidental changes to the internal code of an object can lead to undesirable results, as well as time and money wasted. Therefore, encapsulation is an essential principle to be conscious of when working with OOP languages.

We can imagine encapsulation by considering an example from the real world. In the case of a private safe, it can only be accessed by those with authorized access. This is similar to object-oriented programming, where certain object methods and properties can be private and direct access is prohibited.

The object can be accessed solely by the specified entities, such as the object itself, and methods such as getter and setter. This ensures the internal state of the object is maintained.

How Is Encapsulation Achieved in Python?

While Java realizes encapsulation through the use of access modifiers, such as “private” and “protected,” Python accomplishes this through language and naming conventions. An object’s properties can be encapsulated by either making them private or protected.

It should be noted that these methods don’t actually enforce strict encapsulation, but merely show which variables are intended to be protected or private.

This guides other developers who may be working with your code and hides implementation from those who don’t need to see it. The protected and private variable types are covered next.

Protected Variables

Protected refers to the status of a variable that can be accessed only by code within the class they are part of, as well as any classes derived from this. Access from outside the class is forbidden. In Python, a variable is designated as protected by the single underscore prefix, “_.” An example is shown below.

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def get_name(self):
        return self._name

    def get_age(self):
        return self._age

    def celebrate_birthday(self):
        self._age += 1
        print("Happy birthday, " + self._name + "!")


person1 = Person("Alice", 30)
print(person1.get_name())
print(person1.get_age())
person1.celebrate_birthday()
print(person1.get_age())

First, we define the “Person” class and declare the “int” constructor method. This is called whenever a new instance of the class is made and takes the “name” and “age” arguments. The next lines set the values of the instance variables “_name” and “_age” to the values of the “name” and “age” arguments passed to the “int” function respectively.

We then use two methods to return the values of the “name” and “age” variables. The “_age” variable is then incremented by 1 using the “def celebrate_birthday(self)” method.

The birthday message is then printed to the console, along with the incremented age of the person called “Alice.” This is an instance of the class that was created and assigned to the “person1” variable.

The age and name were retrieved using the getter methods “person1.get_name())” and “person1.get_age()).” The output can be seen in the image below.

encapsulation in python
Using the getter methods “person1.get_name())” and “person1.get_age()).”

Private Variables

Unlike protected members, private properties can only be accessed within the class they belong to. Technically, all members are public in Python and accessible from outside. But we can still indicate where a member should be treated as private. This is done using a double underscore prefix, “__.”

To make access more difficult, Python uses a process known as “name mangling.” When a double underscore prefix is used, the name of the member is “mangled.”

This means the class name it belongs to is added to the start of its name. For an example, consider the following code using similar variables:

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_name(self):
        return self.__name

    def get_age(self):
        return self.__age

    def celebrate_birthday(self):
        self.__age += 1
        print("Happy birthday, " + self.__name + "!")

person1 = Person("Alice", 30)
print(person1.get_name())
print(person1.get_age())
person1.celebrate_birthday()
print(person1.get_age())

print(person1.__age)

The code is largely similar to the previous example, except the class members have been indicated as private. The result of this is seen in the output below, where we receive an attribute error.

This is because the final method, “person1.get_age())” is trying to directly access the private class. However, it fails due to name mangling.

Note that the variables have still been accessed indirectly using the getter methods because they’re defined within the class.

encapsulation in python
Illustrating name mangling.

How Does Non-Encapsulated Code Compare?

To show the difference between encapsulated and non-encapsulated code, see the following slightly modified example:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_name(self):
        return self.name

    def get_age(self):
        return self.age

    def celebrate_birthday(self):
        self.age += 1
        print("Happy birthday, " + self.name + "!")

person1 = Person("Alice", 30)
print(person1.get_name())
print(person1.get_age())
person1.celebrate_birthday()
print(person1.get_age())

print(person1.age)

Here, we haven’t used any underscores to designate the class members as either protected or private. The result of this can be seen in the final function. This accesses the class from outside to print the age once again. See the image below for how this looks.

encapsulation in python
The result of not designating the class members as either protected or private.

Wrapping Up

Overall, encapsulation is a useful technique in object-oriented programming for restricting access to classes and preventing external changes. This helps to make the code more robust, as well as easier to maintain and reuse.

The internal workings can also be changed without affecting the implementation code. While true encapsulation is technically impossible to implement, it can be designated within Python. This is done through the use of naming conventions; namely, underscores.

Frequently Asked Questions

What is encapsulation in Python?

Encapsulation is a technique to hide an object’s data from external classes so that only class members can access it.

 

 

 

 

How do you implement encapsulation in Python?

Encapsulation is implemented using naming conventions. A single or double underscore is added to the beginning of a class member’s name to indicate encapsulation.

Why is encapsulation important?

It’s important because it restricts access to class objects so that the internal state can be maintained. Encapsulation also allows developers to work on an object’s code without disrupting its implementation. This helps to develop more robust code, that is maintainable, flexible, and scalable.

What are some best practices for encapsulation?

Best practices include avoiding direct access to private class members and using getter and setter methods to indirectly access these members.

What's the difference between protected and private members?

Protected members are designated with a single underscore prefix, and can be accessed both from within the class and its derived subclasses. Private members, however, are designated with a double underscore prefix, and can only be accessed from within their class.

Can private class members be accessed externally in Python?

Yes. Python uses name mangling to add the class name to the beginning of the member’s name, but the member can still be accessed. This is intentionally made more difficult through name mangling, however, as doing so can lead to undesirable and unpredictable results.

Can static methods be used with encapsulation?

Technically, yes, encapsulation can be used with static methods. This likely isn’t necessary, however, as these methods can’t access class instance variables anyway.

To top