Python doesn't have true private attributes enforced by the language the way some other languages do — instead, it relies on naming conventions: a single leading underscore signals 'internal, please don't touch this from outside the class' as a courtesy to other developers, while a double leading underscore triggers name mangling, rewriting the attribute internally to include the class name, which makes accidental external access or accidental clashes in subclasses much less likely, though still not truly impossible. Encapsulation is typically paired with methods, or the @property decorator, that provide controlled, validated access to internal state instead of letting external code read or write it directly.
1Understanding Encapsulation
Python doesn't have true private attributes enforced by the language the way some other languages do — instead, it relies on naming conventions: a single leading underscore signals 'internal, please don't touch this from outside the class' as a courtesy to other developers, while a double leading underscore triggers name mangling, rewriting the attribute internally to include the class name, which makes accidental external access or accidental clashes in subclasses much less likely, though still not truly impossible. Encapsulation is typically paired with methods, or the @property decorator, that provide controlled, validated access to internal state instead of letting external code read or write it directly.
Python's philosophy is often summarized as 'we're all consenting adults here' — a single underscore is a strong hint, not a hard barrier, so encapsulation in Python relies on convention and trust rather than a compiler-enforced access modifier.
class BankAccount:
def __init__(self, balance):
self._balance = balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self._balance += amount
account = BankAccount(100)
account.deposit(50)
print(account._balance)2Practical Example
Here is a real-world application of Encapsulation showing how it is used in production Python code.
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def fahrenheit(self):
return self._celsius * 9 / 5 + 32
t = Temperature(20)
print(t.fahrenheit)3Best Practices
Follow these guidelines when working with Encapsulation:
1. Use a single leading underscore to mark attributes/methods as internal implementation details not meant for external use
2. Use @property to expose a controlled, validated 'view' of internal state instead of letting external code set an attribute directly to any value
3. Reserve double leading underscores, name mangling, for cases where accidental overriding or access from a subclass would specifically cause bugs, not as the default privacy convention
Tip: Python's philosophy is often summarized as 'we're all consenting adults here' — a single underscore is a strong hint, not a hard barrier, so encapsulation in Python relies on convention and trust rather than a compiler-enforced access modifier.
class BankAccount:
def __init__(self, balance):
self._balance = balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self._balance += amount
account = BankAccount(100)
account.deposit(50)
print(account._balance)