Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

Encapsulation in Python Private Attributes: Tutorial, Examples, FAQs & Interview Tips

What is Encapsulation?

Encapsulation bundles data (attributes) and the methods that operate on that data into a single unit (class), and restricts direct access to some components. It protects the internal state of an object from unintended modification.

Access Modifiers in Python

Python uses naming conventions rather than strict keywords like private or protected.

ConventionExampleMeaning
No prefixself.namePublic - accessible anywhere
Single underscore _self._salaryProtected - "don't touch from outside" (convention only)
Double underscore __self.__passwordPrivate - name-mangled, harder to access from outside
Access Modifiers
class BankAccount:
    def __init__(self, owner: str, balance: float):
        self.owner = owner          # public
        self._account_type = "savings"  # protected (convention)
        self.__balance = balance    # private (name-mangled)

    def deposit(self, amount: float):
        if amount > 0:
            self.__balance += amount

    def get_balance(self) -> float:
        return self.__balance       # controlled access

account = BankAccount("Alice", 1000)

print(account.owner)           # Alice  (public - fine)
print(account._account_type)   # savings (works but discouraged)
print(account.get_balance())   # 1000   (via method - correct way)

# Direct access to __balance fails
# print(account.__balance)     # AttributeError!

# Name mangling - Python renames it to _ClassName__attr
print(account._BankAccount__balance)  # 1000 (possible but bad practice)

Getters and Setters with @property

@property Decorator
class Temperature:
    def __init__(self, celsius: float = 0):
        self._celsius = celsius

    @property
    def celsius(self) -> float:
        """Getter"""
        return self._celsius

    @celsius.setter
    def celsius(self, value: float):
        """Setter with validation"""
        if value < -273.15:
            raise ValueError("Temperature below absolute zero!")
        self._celsius = value

    @property
    def fahrenheit(self) -> float:
        """Computed property - no setter needed"""
        return self._celsius * 9/5 + 32

    @property
    def kelvin(self) -> float:
        return self._celsius + 273.15

t = Temperature(25)
print(t.celsius)     # 25    - looks like attribute access
print(t.fahrenheit)  # 77.0
print(t.kelvin)      # 298.15

t.celsius = 100      # uses setter
print(t.fahrenheit)  # 212.0

# t.celsius = -300   # ValueError!

Real-World Encapsulation Example

Bank Account
class BankAccount:
    def __init__(self, owner: str, initial_balance: float = 0):
        self.__owner = owner
        self.__balance = initial_balance
        self.__transactions = []

    @property
    def owner(self) -> str:
        return self.__owner

    @property
    def balance(self) -> float:
        return self.__balance

    def deposit(self, amount: float) -> None:
        if amount <= 0:
            raise ValueError("Deposit amount must be positive")
        self.__balance += amount
        self.__transactions.append(f"+${amount:.2f}")

    def withdraw(self, amount: float) -> None:
        if amount <= 0:
            raise ValueError("Withdrawal amount must be positive")
        if amount > self.__balance:
            raise ValueError("Insufficient funds")
        self.__balance -= amount
        self.__transactions.append(f"-${amount:.2f}")

    def get_statement(self) -> str:
        history = "\n".join(self.__transactions) or "No transactions"
        return f"Account: {self.__owner}\nBalance: ${self.__balance:.2f}\n{history}"

acc = BankAccount("Alice", 500)
acc.deposit(200)
acc.withdraw(100)
print(acc.get_statement())
# Account: Alice
# Balance: $600.00
# +$200.00
# -$100.00

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.