w3resource

Python Encapsulation: Using Private and Protected Members in Classes

Introduction to Python Encapsulation

Encapsulation is a fundamental concept in object-oriented programming (OOP) that involves bundling data (attributes) and methods (functions) that operate on the data within a class.

Encapsulation means putting together all the variables (instance variables) and the methods into a single unit called Class. It also means hiding data and methods within an Object. Encapsulation provides the security that keeps data and methods safe from inadvertent changes. Programmers sometimes refer to encapsulation as using a “black box,” or a device that you can use without regard to the internal mechanisms.

In Python, encapsulation is achieved by using access specifiers like private and protected members. Let's explore how to use private and protected members in Python classes through examples.

Example 1: Using Protected Members

Protected members are intended to be accessible only within the class and its subclasses. In Python, protected members are indicated by a single underscore (_) prefix.

Code:

# Base class
class Animal:
    def __init__(self, name):
        self._name = name  # Protected attribute

    def _speak(self):
        return f"{self._name} makes a sound."  # Protected method

# Derived class
class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self._breed = breed  # Protected attribute specific to Dog

    def get_info(self):
        return f"{self._name} is a {self._breed}."  # Accessing protected attributes

    def speak(self):
        return self._speak()  # Accessing protected method

# Creating an instance of Dog
dog = Dog("Buddy", "Golden Retriever")

# Accessing protected members from within the class
print(dog.get_info())  # Output: Buddy is a Golden Retriever.
print(dog.speak())     # Output: Buddy makes a sound.

Explanation:

Protected Attributes:

  • In the Animal class, '_name' is a protected attribute. It can be accessed directly within the class and any subclasses.
  • The Dog class has an additional protected attribute '_breed'.

Protected Methods:

  • The _speak method in the Animal class is protected. It is meant to be used within the class or subclasses but not from outside.

Accessing Protected Members:

  • The "get_info" method in the Dog class accesses the protected '_name' and '_breed' attributes to return information about the dog.
  • The speak method in the Dog class accesses the protected "_speak" method of the 'Animal' class.

Example 2: Using Private Members

Private members are intended to be accessible only within the class itself. In Python, private members are indicated by a double underscore (__) prefix.

Code:

# Class with private members
class BankAccount:
    def __init__(self, owner, balance):
        self.__owner = owner       # Private attribute
        self.__balance = balance   # Private attribute

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount  # Modifying private attribute
        return self.__balance

    def withdraw(self, amount):
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount  # Modifying private attribute
        return self.__balance

    def get_balance(self):
        return f"Account holder: {self.__owner}, Balance: ${self.__balance}"

# Creating an instance of BankAccount
account = BankAccount("Petre Matauc", 1000)

# Interacting with private members through public methods
print(account.deposit(400))   # Output: 1400
print(account.withdraw(100))  # Output: 1300
print(account.get_balance())  # Output: Account holder: Petre Matauc, Balance: $1300

# Trying to access private members directly (will raise an AttributeError)
# print(account.__balance)  # Uncommenting this line will cause an error

Explanation:

Private Attributes:

  • The '__owner' and '__balance' attributes in the BankAccount class are private. They cannot be accessed directly from outside the class.

Public Methods for Access:

  • The class provides public methods ('deposit', 'withdraw', and 'get_balance') to interact with the private attributes.
  • These methods allow controlled access to modify and retrieve the values of the private attributes.
  • Encapsulation in Action:
    • Encapsulation hides the internal state of the object (‘__balance’) from the outside world, ensuring that it can only be changed through the defined methods.

    Example 3: Accessing Private Members Using Name Mangling

    Python provides a way to access private members from outside the class using a technique called name mangling.

    Code:

    # Class with private members
    class Person:
        def __init__(self, name):
            self.__name = name  # Private attribute
    
        def greet(self):
            return f"Hello, my name is {self.__name}."
    
    # Creating an instance of Person
    person1 = Person("Marina Shouhei")
    
    # Accessing the private attribute using name mangling
    print(person1.greet())       # Hello, my name is Marina Shouhei.
    print(person1._Person__name) # Output: Marina Shouhei (accessing private attribute)
    

    Explanation:

    Name Mangling:

    • Private attributes in Python are not truly hidden. They are renamed internally using a technique called name mangling.
    • For an attribute named __name in a class 'Person', Python internally changes it to '_Person__name'.

    Accessing Private Members:

    • Although private members are not meant to be accessed directly, name mangling allows access if needed (e.g., 'person1._Person__name').
    • However, this practice is generally discouraged as it goes against the principle of encapsulation.

    Summary:

    • Encapsulation in Python allows restricting access to certain attributes and methods to protect an object's internal state.
    • Protected Members: Use a single underscore (_) to indicate that an attribute or method is protected and should only be accessed within the class and its subclasses.
    • Private Members: Use a double underscore (__) to indicate that an attribute or method is private and should only be accessed within the class itself.
    • Name Mangling: Python uses name mangling to make private attributes harder to access, but they can still be accessed if needed by using the mangled name.

    By using encapsulation, you can create classes that are more secure and maintainable. This ensures that the internal state of an object can only be modified in controlled ways.

    

    Become a Patron!

    Follow us on Facebook and Twitter for latest update.