← Back to Python Course | Chapter 7: OOP | Lesson 7 of 11

Python Encapsulation

What is Encapsulation?

Encapsulation bundles an object's data together with the methods that operate on it and limits how much of that data outside code can touch directly -- the goal is preventing some other part of the program from putting an object into an invalid state by poking at its internals.

Example: What is Encapsulation?

python
class Account:
    def __init__(self, balance):
        self.balance = balance
    def deposit(self, amount):
        self.balance += amount

a = Account(100)
a.deposit(50)
print(a.balance)

Protected Members

A single leading underscore (_balance) is purely a naming convention in Python, not an enforced restriction -- it signals to other developers 'this is internal, please don't touch it directly from outside the class,' but nothing stops them from doing so anyway.

Example: Protected Members

python
class Account:
    def __init__(self, balance):
        self._balance = balance  # convention: internal use only

a = Account(100)
print(a._balance)  # still accessible, but discouraged

Private Members

A double leading underscore (__balance) triggers Python's name-mangling mechanism, which makes the attribute genuinely harder (though not impossible) to access accidentally from outside the class -- this is the closest Python gets to true private attributes.

Example: Private Members

python
class Account:
    def __init__(self, balance):
        self.__balance = balance

a = Account(100)
print(a._Account__balance)  # name-mangled, hard to access directly

Name Mangling

Under the hood, Python renames a double-underscore attribute from __balance to _ClassName__balance, which is why you'll see that mangled name if you inspect an object's __dict__ -- it's designed to prevent accidental name collisions in subclasses, not to be unbreakable security.

Example: Name Mangling

python
class Account:
    def __init__(self, balance):
        self.__balance = balance

a = Account(100)
print(a.__dict__)

Getter and Setter Methods

Getter and setter methods (or the @property decorator) give you a controlled doorway to a private attribute -- a setter can validate a new balance isn't negative before accepting it, something plain attribute assignment can't do on its own.

Example: Getter and Setter Methods

python
class Account:
    def __init__(self, balance):
        self.__balance = balance
    def get_balance(self):
        return self.__balance
    def set_balance(self, value):
        if value >= 0:
            self.__balance = value

a = Account(100)
a.set_balance(200)
print(a.get_balance())

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.