Validation Strategies
Comprehensive Validation Approaches
1. Type-Based Validation
def validate_type(value, expected_type, field_name):
if not isinstance(value, expected_type):
raise TypeError(f"{field_name} must be of type {expected_type.__name__}")
class User:
def __init__(self, name, age, email):
validate_type(name, str, "Name")
validate_type(age, int, "Age")
validate_type(email, str, "Email")
self.name = name
self.age = age
self.email = email
2. Complex Validation Patterns
import re
class ValidationUtils:
@staticmethod
def validate_email(email):
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, email):
raise ValueError("Invalid email format")
@staticmethod
def validate_phone_number(phone):
phone_pattern = r'^\+?1?\d{10,14}$'
if not re.match(phone_pattern, phone):
raise ValueError("Invalid phone number format")
Validation Strategy Flowchart
graph TD
A[Validation Strategy] --> B[Type Checking]
A --> C[Format Validation]
A --> D[Range Constraints]
A --> E[Custom Validation Rules]
Advanced Validation Techniques
3. Decorator-Based Validation
def validate_range(min_value=None, max_value=None):
def decorator(func):
def wrapper(self, value):
if min_value is not None and value < min_value:
raise ValueError(f"Value must be at least {min_value}")
if max_value is not None and value > max_value:
raise ValueError(f"Value must be at most {max_value}")
return func(self, value)
return wrapper
return decorator
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
@validate_range(min_value=0, max_value=1000)
def set_price(self, price):
self._price = price
Validation Strategy Comparison
Strategy |
Complexity |
Flexibility |
Performance |
Use Case |
Type Checking |
Low |
Limited |
High |
Basic type validation |
Regex Validation |
Medium |
High |
Medium |
Complex format checks |
Decorator Validation |
High |
Very High |
Low |
Advanced constraints |
Validation Best Practices
- Fail fast and provide clear error messages
- Use type hints for additional clarity
- Implement comprehensive error handling
- Keep validation logic modular and reusable
4. Comprehensive Validation Class
class DataValidator:
@classmethod
def validate(cls, data, rules):
errors = {}
for field, field_rules in rules.items():
value = data.get(field)
for rule in field_rules:
try:
rule(value)
except ValueError as e:
errors[field] = str(e)
if errors:
raise ValueError(f"Validation failed: {errors}")
## Example usage
def non_empty(value):
if not value:
raise ValueError("Field cannot be empty")
def validate_age(value):
if not isinstance(value, int) or value < 0 or value > 120:
raise ValueError("Invalid age")
validation_rules = {
'name': [non_empty],
'age': [validate_age]
}
try:
DataValidator.validate({
'name': 'John Doe',
'age': 30
}, validation_rules)
except ValueError as e:
print(e)
Key Takeaways
With LabEx's comprehensive approach, developers can implement robust validation strategies that ensure data integrity and prevent potential runtime errors. The key is to choose the right validation technique based on specific requirements and complexity of the validation logic.