Monday, March 28, 2022

Encapsulation in Python

Encapsulation is one of the four fundamental OOPS concepts. The other three being Inheritance, Polymorphism, Abstraction

What is Encapsulation

The concept of Encapsulation is to keep together the implementation (code) and the data it manipulates (variables). Having proper encapsulation ensures that the code and data both are safe from misuse by outside entity. That is done by restricting access to the methods and variables and any change to the variables done only through methods.

Encapsulation in Python

In any object oriented language first step towards encapsulation is the class and encapsulation in Python also starts from a class as the class encapsulates the methods and variables. When a Python class is created it contains the methods and the variables. Since it’s the code in the methods that operates on the variables, in a properly encapsulated Python class, methods should define how member variables can be used.

But that’s where the things differ a bit in Python from a language like Java where we have access modifiers like public, private. In Python there are no explicit access modifiers and everything written with in the class (methods and variables) are public by default.

For example in the class Person there are two variables as you can see those variables are accessed through a method as well as directly.

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

  def display(self):
    print(self.name)
    print(self.age)

person = Person('John', 40)
#accessing using class method
person.display()
#accessing directly from outside
print(person.name)
print(person.age)

Output

John
40
John
40

Access control in Python

If everything inside a class is public then how to have access control and how to have proper encapsulation in Python?

In Python though there are no explicit access modifiers but using underscores (_) you can make a variable private.

Using single underscore

Using a single leading underscore is merely a convention. A name prefixed with an underscore in Python (as example _name) should be treated as a non-public part of the API (whether it is a function, a method or a data member).

As mentioned it is just a convention and a leading underscore doesn’t actually make any variable or method private or protected. It’s just that if you see a variable or method with a leading underscore in Python code you should follow the convention that it should be used internally with in a class.

For example in class Person if age variable is changed and it is prefixed with underscore.

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

  def display(self):
    print(self.name)
    print(self._age)

person = Person('John', 40)
#accessing using class method
person.display()
#accessing directly from outside
print(person.name)
print(person._age)

Output

John
40
John
40

As you can see these variables can still be accessed from outside the class.

Using double underscore (making it private)

If you really want to make a class member (member or variable) private in Python you can do it by prefixing a variable or method with double underscores. Here note that Python provides a limited support for private modifier using a mechanism called name mangling and it is still possible to access such class member from outside the class.

In Python any identifier of the form __var (at least two leading underscores, at most one trailing underscore) is rewritten by the Python interpreter in the form _classname__var, where classname is the current class name. This mechanism of name changing is known as name mangling in Python.

For example in class Person age variable is changed and it is prefixed with two leading underscores.

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

  def display(self):
    print(self.name)
    print(self.__age)

person = Person('John', 40)
#accessing using class method
person.display()
#accessing directly from outside
print('Trying to access variables from outside the class ')
print(person.name)
print(person.__age

Output

John
40
Trying to access variables from outside the class
John
Traceback (most recent call last):
  File "Person.py", line 16, in <module>
    print(person.__age)
AttributeError: 'Person' object has no attribute '__age'

As you can see variables can still be accessed using the method which is part of the class but age (which is a private variable) can’t be accessed directly from outside now.

Using getter and setter methods to access private variables

To access and change private variables accessor (getter) methods and mutator (setter methods) should be used which are part of the class.

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

  def display(self):
    print(self.name)
    print(self.__age)

  def getAge(self):
    print(self.__age)

  def setAge(self, age):
    self.__age = age

person = Person('John', 40)
#accessing using class method
person.display()
#changing age using setter
person.setAge(45)
person.getAge()

Output

John
40
45

That's all for this topic Encapsulation in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python Installation on Windows
  2. Python First Program - Hello World
  3. Method Overriding in Python
  4. Python for Loop With Examples
  5. Difference Between Function and Method in Python

You may also like-

  1. Constructor in Python - __init__() function
  2. self in Python
  3. Python count() method - Counting Substrings
  4. Python Exception Handling - try,except,finally
  5. How to Read File From The Last Line in Java
  6. Marker Interface in Java
  7. How Linked List class works internally in Java
  8. Race Condition in Java Multi-Threading