Python is a popular programming language which is known for its simplicity and readability. In Python, encapsulation is a fundamental concept that revolves around bundling data and methods together within a class and restricting direct access to the class's internal state from the outside. Importantly, encapsulation allows you to control how the data is accessed and modified, which provides better security and maintainability in your code.In this article we will talk about encapsulation in detail.
This blog explains the basics of access specifiers in Python, the advantages of Encapsulation, and its relations to class variables.
What is Encapsulation in Python?
Encapsulation is a fundamental concept of object-oriented programming(OOP). It involves combining data and its related methods into a single unit called “class”, which restricts direct access to variables and methods and helps prevent unintended changes to the data.
This promotes better code organization and reusability. Overall, encapsulation is essential for building robust software systems.
In object-oriented programming, encapsulation is a mechanism that enables the bundling of data and methods and restricts access to the data from outside the class. Private and public variables are two ways of controlling access to class variables.
A real-life example of this concept could be a car. The car's driver can interact with various features, such as the steering wheel, pedals, and dashboard. These features are accessible to the driver and are similar to public variables.
However, the driver cannot see or interact with many parts of the car, such as the engine and transmission. These parts are similar to private variables, accessible only within the class or object.
By using private and public variables in encapsulation, we can control access to an object's data and ensure that it is only modified in a controlled way.
It makes managing the object's behavior easier and protects its internal data from being accidentally modified.
How is Encapsulation Achieved in Python?
## How is Encapsulation Achieved in Python?
Encapsulation in Python is achieved through the use of access modifiers which restrict access to the methods and variables of a class. This helps in bundling the data (variables) and the methods that act on the data into a single unit or class. Python primarily uses two types of access modifiers: public and private.
1. Public Members: In Python, members of a class that are accessible from outside the class are public. By default, all attributes and methods in a Python class are public. They can be accessed using the dot operator on an object.
2. Private Members: To make an attribute or method private (i.e., accessible only within the class), you precede its name with two underscores (`__`). This triggers a name mangling process, where the interpreter modifies the name of the variable in a way that makes it harder to create subclasses that accidentally override the private attributes and methods.
For example:
Python
Python
class EncapsulatedObject: def __init__(self): self.public_var = "I am accessible" self.__private_var = "I am not easily accessible"
def public_method(self): return "This is a public method"
def __private_method(self): return "This is a private method"
obj = EncapsulatedObject() print(obj.public_var) # Accessible print(obj.public_method()) # Accessible # print(obj.__private_var) # This will raise an error # print(obj.__private_method()) # This will raise an error
You can also try this code with Online Python Compiler
In this example, `public_var` and `public_method()` are accessible from outside the class, whereas `__private_var` and `__private_method()` are not, showcasing encapsulation by restricting access to certain class components.
Access Modifiers in Python Encapsulation
The access modifiers in Python Encapsulation are used to restrict the access of the class data members and member functions from outside of the class. The access modifiers are used to protect the internal data of the class and the instances associated with it.
There are the following three types of access modifiers that are supported by the Pyhton encapsulation.
Public Access Modifier - It is the default for member variables and methods for a class. Here, the data member and methods are accessible outside or inside of the class.
Private Access Modifier - A double underscore prefix denotes protected members before their name. Here, the data member and methods are accessed only within the class.
Protected Access Modifier - A single underscore prefix denotes protected members before their name. Here, the data member and methods are accessed only within the class and the class that is inherited from the protected class.
Now, We will discuss each of the above-mentioned access modifiers in detail.
1. Public Access Modifier
These variables or methods are the default type members. The public members are specified without any explicit keywords. The member variables and methods defined as public are accessed both outside and inside the class.
Example:
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
def display(self):
print("Employee Name:", self.name)
print("Employee Age:", self.age)
s = Student("Kartik Singh", 22)
s.display()
Output:
Employee Name: Kartik Singh
Employee Age: 22
In this example, we can that we create a class named “Employee” which has data members as “name” and “age”. The class has a member function as “display”. Since we do not specify the access specifier type, it is public by default. Here, we can see that we are accessing the function “display” outside the class.
2. Protected Access Modifier
These variables or methods can be accessed only within the class and its subclasses. A single underscore prefix denotes protected members before their name.
The __init__ method runs as soon as an object of a class is instantiated.
Example:
class Person:
def __init__(self, name, age, _id):
self.name = name
self.age = age
self._id = _id
def display(self):
print("Name:", self.name)
print("Age:", self.age)
print("ID:", self._id)
class Student(Person):
def __init__(self, name, age, _id, marks):
super().__init__(name, age, _id)
self.marks = marks
def display(self):
super().display()
print("Marks:", self.marks)
In this example, the Person class has a protected variable called "_id." This variable is intended to be used only within the class and its subclasses. The Student class is a subclass of Person with a variable called "marks."
Both classes have a method called "display" that prints out the values of their variables. The Student class overrides the "display" method of the Person class to include the "marks" variable.
Using the single underscore prefix before the "_id" variable indicates that it is a protected variable. This means that it should not be accessed or modified from outside the class or its subclasses, but it should be accessed from within the class or its subclasses.
To see the output, we need to create objects of the classes and call their methods. Here's an example:
In this example, we create a Person object called "person" with the name "John," age 25, and ID 12345. We also created a Student object called "student" with the name "Jane," age 20, ID 54321, and marks 90.
We then call the "display" method of the person object, which prints out its name, age, and ID. We also call the "display" method of the student object, which prints out its name, age, ID, and marks.
3. Private Access Modifier
In Python, private members in encapsulation are variables or methods intended to be accessed only within the class. A double underscore prefix denotes private members before their names.
Example:
class BankAccount:
def __init__(self, name, balance):
self.name = name
self.__balance = balance
def deposit(self, amount):
self.__balance += amount
print("Deposit successful. New balance:", self.__balance)
def withdraw(self, amount):
if amount > self.__balance:
print("Insufficient balance.")
else:
self.__balance -= amount
print("Withdrawal successful. New balance:", self.__balance)
def __show_balance(self):
print("Current balance:", self.__balance)
In this example, the BankAccount class has a private variable called "__balance." This variable is intended to be used only within the class itself. The class also has two methods, "deposit" and "withdraw," which modify the balance variable based on the amount specified.
Additionally, the class has a private method called "__show_balance," intended to be used only within the class.
Using the double underscore prefix before the "balance" and "show_balance" variables, we indicate that they are private variables and methods, respectively.
An example demonstration of the above code is as follows:
In this example, we create a BankAccount object called "account" with the name "John" and a balance of 1000. We then call the "deposit" and "withdraw" methods of the account object to modify its balance.
When we try to call the "__show_balance" method of the account object, we get an AttributeError because the method is private and cannot be accessed outside the class.
Overall, private members provide a way to restrict access to data and methods and help prevent accidental modification of the internal state of an object.
Example of Python Encapsulation
Let's explore an example code to show how encapsulation is implemented in Python. We will be using a Student class:
Python
Python
class Student: def __init__(self, name, age): self.__name = name # Private attribute self.__age = age # Private attribute
def get_name(self): return self.__name
def set_name(self, name): self.__name = name
def get_age(self): return self.__age
def set_age(self, age): if age >= 0: self.__age = age else: print("Age cannot be negative!") # Creating an instance of the Student class student1 = Student("Alice", 20) # Accessing private attributes using getter methods print("Student's name:", student1.get_name()) print("Student's age:", student1.get_age()) # Using setter methods to update private attributes student1.set_name("Bob") student1.set_age(22) print("Updated student's name:", student1.get_name()) print("Updated student's age:", student1.get_age()) # Trying to set a negative age (will print an error message) student1.set_age(-1)
You can also try this code with Online Python Compiler
In the above output, we used special methods (getters and setters) to work with the private details (attributes) of the Student class. When we tried to set a negative age, the program showed an error message, which shows how encapsulation helps maintain the data integrity and provides controlled access to class attributes.
Why do we need Encapsulation in Python?
Encapsulation forms an essential part of all object-oriented programming languages. Encapsulation is needed in Python as it helps to restrict access to some of the components of an object to the outside world. Using encapsulation in Python helps users to not access the state values for all the variables of an individual object.
Using Encapsulation in Python we can hide both data functions and data members or methods that are associated with an instance of a class. Encapsulation provides more flexibility in Python as it enables users to set variables to either read or write. Encapsulation helps to introduce code reusability and helps write cleaner codes. Thus, we can say that encapsulation in Python is a means of facilitating Data Abstraction.
Consider the example of a car - While we are driving a car, do we ever care or need to know how the car was manufactured? Do we need to know how the parts we assembled and it was designed? The answer to all these questions is No, as we are interested in driving the car without knowing these details.
Similarly, we use encapsulation in Python, so suppose we have a variable that is not used on the outside of an object. Now, this variable can be bundled with methods that provide read or write access. Here, encapsulation in Python has helped to control the access to objects' data members and methods.
Advantages of Python Encapsulation
The advantages of encapsulation in Python include the following:
Data hiding Encapsulation helps to maintain the integrity of an object's data by preventing external modification.
Easier to understand It reduces code complexity by hiding implementation details, making code easier to understand and maintain.
Code reusability Encapsulation enables code reuse by creating a public interface for a class that can be used by other parts of the program.
Improved maintainability It provides better control over the behavior of an object, as changes can be made to the implementation without affecting the rest of the program.
Better control over class properties Encapsulation helps to prevent naming conflicts by restricting the scope of variables and methods to the class where they are defined.
Disadvantages of Python Encapsulation
Complexity: Encapsulation can increase the complexity of the codebase, making it harder for new developers to understand the internal workings of classes.
Overhead: It may introduce performance overhead due to getter and setter methods, especially if not properly optimized.
Tight Coupling: Can lead to tightly coupled code if not carefully designed, making modifications and maintenance challenging.
Accessibility: Restricts direct access to class fields, which might be inconvenient in some scenarios where direct access is necessary for efficiency.
Inflexibility: Overuse of encapsulation might lead to inflexible code, making it hard to extend or modify the behavior of classes without altering their interfaces.
Frequently Asked Questions
What technique is used for encapsulation?
In encapsulation, access modifiers such as private, protected, and public are used to bundle data and methods within a class, restricting external access and protecting the integrity of the data.
What is abstraction and encapsulation in Python?
Abstraction is an OOP concept in Python that refers to performing the necessary tasks hiding the internal details from the outer world. Encapsulation is an OOP concept used to restrict the access of data members and functions in a class.
Should you encapsulate in Python?
Yes, encapsulation is recommended in Python as it helps to organize and structure the code. Encapsulation provides various advantages like data hiding, code reusability, code organization, and data protection. Therefore, it is important to use encapsulation in Python.
What distinguishes public, private, and protected access specifiers in Python?
No prefix denotes the public access specifier, a double underscore prefix denotes the private access specifier, and a single underscore prefix denotes the protected access specifier.
Conclusion
In this blog, we explored the concept of Encapsulation in Python in detail. We hope it increased the reader's understanding of OOPS concepts concerning Python. We learned the advantages that are associated with encapsulation. We discussed the need for encapsulation in Python. We also learned about the different types of access modifiers available in Python and discussed each of them in detail stating relevant examples for the same.