
Python
Advanced encapsulation includes name mangling for true privacy, sophisticated property patterns, computed attributes, and validation chains. These techniques create robust, maintainable object models.
Double underscore prefix triggers name mangling, providing stronger privacy than single underscore convention.
class BankAccount:
def __init__(self, owner, balance):
self.__owner = owner # Name mangled
self.__balance = balance # Name mangled
self._pin = "1234" # Private convention
def __private_method(self):
"""Truly private method"""
return f"Balance: {self.__balance}"
def get_balance(self, pin):
if pin == self._pin:
return self.__balance
raise ValueError("Invalid PIN")
account = BankAccount("Alice", 1000)
# Can't access mangled names directly
try:
print(account.__balance) # Error!
except AttributeError as e:
print(f"Error: {e}")
# Name mangled to _BankAccount__balance
print(account._BankAccount__balance) # Possible but strongly discouraged
# Use public method
print(account.get_balance("1234"))Create sophisticated property validation chains.
class Email:
def __init__(self, value=None):
self._value = None
if value:
self.value = value
@property
def value(self):
return self._value
@value.setter
def value(self, v):
if not self._is_valid(v):
raise ValueError(f"Invalid email: {v}")
self._value = v
@staticmethod
def _is_valid(email):
return "@" in email and "." in email.split("@")[1]
class User:
def __init__(self, name, email):
self.name = name
self.__email = Email()
self.email = email # Calls setter
@property
def email(self):
return self.__email.value
@email.setter
def email(self, value):
self.__email.value = value
user = User("Alice", "alice@example.com")
print(user.email)
try:
user.email = "invalid-email"
except ValueError as e:
print(f"Error: {e}")Cache computed properties for performance while maintaining lazy initialization.
class CachedProperty:
def __init__(self, func):
self.func = func
self.name = func.__name__
def __get__(self, obj, objtype=None):
if obj is None:
return self
cache_name = f"_cached_{self.name}"
if not hasattr(obj, cache_name):
setattr(obj, cache_name, self.func(obj))
return getattr(obj, cache_name)
class DataAnalyzer:
def __init__(self, data):
self.data = data
@CachedProperty
def mean(self):
print("Computing mean...")
return sum(self.data) / len(self.data)
@CachedProperty
def median(self):
print("Computing median...")
sorted_data = sorted(self.data)
n = len(sorted_data)
return sorted_data[n//2]
analyzer = DataAnalyzer([1, 2, 3, 4, 5])
print(f"Mean: {analyzer.mean}")
print(f"Mean again: {analyzer.mean}") # No recomputation
print(f"Median: {analyzer.median}")Create immutable or sealed objects that can't be modified after creation.
class Sealed:
"""Base class for sealed objects"""
__slots__ = ()
def __setattr__(self, name, value):
if hasattr(self, '__dict__'):
raise AttributeError("Cannot modify sealed object")
super().__setattr__(name, value)
class Point(Sealed):
__slots__ = ('_x', '_y')
def __init__(self, x, y):
object.__setattr__(self, '_x', x)
object.__setattr__(self, '_y', y)
@property
def x(self):
return self._x
@property
def y(self):
return self._y
point = Point(10, 20)
print(f"Point: ({point.x}, {point.y})")
try:
point.x = 30 # Error!
except AttributeError as e:
print(f"Error: {e}")import hashlib
class SecureString:
def __init__(self, value=None):
self._encrypted = None
if value:
self.value = value
@property
def value(self):
if self._encrypted:
return f"[ENCRYPTED - {len(self._encrypted)} chars]"
return None
@value.setter
def value(self, plaintext):
self._encrypted = hashlib.sha256(plaintext.encode()).hexdigest()
def verify(self, plaintext):
return self._encrypted == hashlib.sha256(plaintext.encode()).hexdigest()
class CredentialManager:
def __init__(self):
self.__password = SecureString()
def set_password(self, password):
self.__password.value = password
def verify_password(self, password):
return self.__password.verify(password)
def get_password_info(self):
return self.__password.value
manager = CredentialManager()
manager.set_password("super_secret_123")
print(manager.get_password_info())
print(f"Correct? {manager.verify_password('super_secret_123')}")
print(f"Wrong? {manager.verify_password('wrong_password')}")class ImmutableConfig:
def __init__(self, **kwargs):
self.__data = kwargs
self.__frozen = True
def __getattr__(self, name):
if name.startswith('_'):
return object.__getattribute__(self, name)
if name in self.__data:
return self.__data[name]
raise AttributeError(f"No config: {name}")
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value)
elif hasattr(self, '_ImmutableConfig__frozen'):
raise AttributeError("Config is immutable")
else:
super().__setattr__(name, value)
config = ImmutableConfig(
debug=True,
timeout=30,
max_retries=3
)
print(config.debug)
print(config.timeout)
try:
config.debug = False # Error!
except AttributeError as e:
print(f"Error: {e}")| Concept | Remember |
|---|---|
| Name Mangling | Double underscore for stronger privacy |
| Property Chains | Compose validation and access control |
| Cached Properties | Cache expensive computations |
| Sealed Objects | Prevent modification after creation |
| Encryption | Protect sensitive data at property level |
| Immutability | Create unchangeable objects |
| Access Control | Multi-level privacy (single _, double __, property) |
| Robustness | Enforce invariants at the object level |
Finish with advanced magic methods patterns.
Advanced: Magic Methods & Dunder →
Ready to practice? Try challenges or explore more concepts
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward