Practical Validation Patterns
Introduction to Validation Patterns
Practical validation patterns help developers create robust and reliable code by implementing effective type checking and data validation strategies.
Decorator-Based Validation
def validate_sequence(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, (list, tuple, str, range)):
raise TypeError(f"Invalid sequence type: {type(arg)}")
return func(*args, **kwargs)
return wrapper
@validate_sequence
def process_sequence(data):
return list(data)
## Usage examples
print(process_sequence([1, 2, 3]))
print(process_sequence("LabEx"))
## print(process_sequence(42)) ## Raises TypeError
Validation Pattern Strategies
graph TD
A[Validation Patterns] --> B[Type Checking]
A --> C[Data Integrity]
A --> D[Error Handling]
B --> E[isinstance]
B --> F[Duck Typing]
C --> G[Length Validation]
C --> H[Content Validation]
D --> I[Exception Handling]
D --> J[Graceful Degradation]
Comprehensive Validation Approach
Validation Type |
Method |
Purpose |
Type Checking |
isinstance() |
Verify object type |
Length Validation |
len() |
Check collection size |
Content Validation |
all() |
Validate element properties |
Safe Access |
get() |
Prevent KeyError |
Advanced Validation Techniques
def advanced_sequence_validator(data,
min_length=0,
max_length=float('inf'),
element_type=None):
## Comprehensive sequence validation
if not isinstance(data, (list, tuple, str, range)):
raise TypeError("Invalid sequence type")
## Length validation
if not (min_length <= len(data) <= max_length):
raise ValueError(f"Sequence length must be between {min_length} and {max_length}")
## Element type validation
if element_type:
if not all(isinstance(item, element_type) for item in data):
raise TypeError(f"All elements must be of type {element_type}")
return True
## Usage examples
try:
advanced_sequence_validator([1, 2, 3], min_length=1, max_length=5, element_type=int)
advanced_sequence_validator("LabEx", min_length=3, max_length=10)
except (TypeError, ValueError) as e:
print(f"Validation Error: {e}")
Error Handling Patterns
def safe_sequence_processing(data, default=None):
try:
## Attempt to convert to list if not already a sequence
if not isinstance(data, (list, tuple, str, range)):
data = list(data)
## Process sequence
return [item for item in data if item is not None]
except Exception as e:
print(f"Processing error: {e}")
return default or []
## Safe processing examples
print(safe_sequence_processing([1, 2, None, 3]))
print(safe_sequence_processing(42, default=[]))
Context Manager for Validation
class SequenceValidator:
def __init__(self, data):
self.data = data
def __enter__(self):
if not isinstance(self.data, (list, tuple, str, range)):
raise TypeError("Invalid sequence type")
return self.data
def __exit__(self, exc_type, exc_value, traceback):
## Optional cleanup or logging
pass
## Usage
try:
with SequenceValidator([1, 2, 3]) as validated_data:
print(validated_data)
except TypeError as e:
print(f"Validation Error: {e}")
Best Practices
- Use multiple validation layers
- Implement clear error messages
- Provide default behaviors
- Use type hints for additional clarity
By applying these practical validation patterns, developers can create more resilient and self-documenting Python code, ensuring data integrity and reducing runtime errors.