Validation Techniques
Built-in Validation Methods
Type Checking with isinstance()
def process_data(value):
if not isinstance(value, (int, float, str)):
raise TypeError("Invalid input type")
return value
Using assert Statements
def divide_numbers(a, b):
assert b != 0, "Division by zero is not allowed"
return a / b
Advanced Validation Techniques
Decorator-based Validation
def validate_type(*types):
def decorator(func):
def wrapper(*args, **kwargs):
for arg, expected_type in zip(args, types):
if not isinstance(arg, expected_type):
raise TypeError(f"Expected {expected_type}, got {type(arg)}")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_type(int, int)
def add_numbers(a, b):
return a + b
Validation Strategies Comparison
Technique |
Pros |
Cons |
isinstance() |
Simple, built-in |
Limited complex validation |
Assert |
Quick checks |
Can be disabled |
Decorators |
Reusable, flexible |
Slight performance overhead |
Complex Validation Flow
graph TD
A[Input Parameters] --> B{Type Validation}
B -->|Pass| C{Range Validation}
B -->|Fail| D[Raise TypeError]
C -->|Pass| E{Custom Validation}
C -->|Fail| F[Raise ValueError]
E -->|Pass| G[Execute Function]
E -->|Fail| H[Raise Custom Exception]
External Validation Libraries
Using Third-Party Libraries
- Pydantic
- Marshmallow
- Cerberus
from pydantic import BaseModel, validator
class User(BaseModel):
name: str
age: int
@validator('age')
def validate_age(cls, v):
if v < 0 or v > 120:
raise ValueError('Invalid age')
return v
Best Practices
- Choose validation method based on complexity
- Keep validation logic clean and focused
- Use type hints for additional clarity
At LabEx, we recommend combining multiple validation techniques for robust input handling.
- Minimize validation overhead
- Use lazy validation when possible
- Consider compiled validation for performance-critical code