Advanced Extension Patterns
Metaclasses provide a powerful way to customize class creation:
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
def __init__(self):
self.connection = None
def connect(self):
if not self.connection:
self.connection = "Active Connection"
return self.connection
Decorator-Based Class Extension
def validate_parameters(func):
def wrapper(self, *args, **kwargs):
if not all(args):
raise ValueError("Invalid parameters")
return func(self, *args, **kwargs)
return wrapper
class DataProcessor:
@validate_parameters
def process_data(self, data):
return f"Processed: {data}"
Class Composition Patterns
classDiagram
class BaseStrategy {
+execute()
}
class ConcreteStrategyA {
+execute()
}
class ConcreteStrategyB {
+execute()
}
class Context {
-strategy: BaseStrategy
+set_strategy()
+execute()
}
BaseStrategy <|-- ConcreteStrategyA
BaseStrategy <|-- ConcreteStrategyB
Context o-- BaseStrategy
Dynamic Class Creation
def create_model_class(table_name, fields):
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
attrs = {
'__init__': __init__,
'table_name': table_name
}
return type(table_name, (), attrs)
## Dynamic class generation
UserModel = create_model_class('users', ['id', 'name', 'email'])
user = UserModel(id=1, name='John', email='[email protected]')
Extension Strategies Comparison
Pattern |
Use Case |
Complexity |
Flexibility |
Inheritance |
Basic extension |
Low |
Moderate |
Composition |
Flexible behavior |
Moderate |
High |
Metaclass |
Advanced customization |
High |
Very High |
Decorators |
Behavior modification |
Low |
Moderate |
Advanced Mixin Techniques
class CacheMixin:
_cache = {}
def cache_result(self, key):
def decorator(func):
def wrapper(*args, **kwargs):
if key not in self._cache:
self._cache[key] = func(*args, **kwargs)
return self._cache[key]
return wrapper
return decorator
class DataService(CacheMixin):
@CacheMixin.cache_result('user_data')
def get_user_data(self, user_id):
## Simulated data retrieval
return f"Data for user {user_id}"
Proxy Pattern Implementation
class ServiceProxy:
def __init__(self, service):
self._service = service
self._cache = {}
def __getattr__(self, name):
def cached_method(*args):
cache_key = (name, args)
if cache_key not in self._cache:
method = getattr(self._service, name)
self._cache[cache_key] = method(*args)
return self._cache[cache_key]
return cached_method
class RemoteService:
def expensive_operation(self, param):
## Simulated expensive computation
return f"Result for {param}"
## Usage in LabEx Python environment
service = ServiceProxy(RemoteService())
Best Practices for Advanced Extensions
- Use composition over deep inheritance
- Leverage decorators for cross-cutting concerns
- Implement metaclasses sparingly
- Keep extensions modular and focused
- Consider performance implications
Potential Pitfalls
- Overcomplicating class design
- Performance overhead with dynamic techniques
- Reduced code readability
- Increased complexity of class interactions