Validación práctica de tipos
Descripción general de las técnicas de validación de tipos
La validación de tipos garantiza la integridad de los datos y evita errores en tiempo de ejecución mediante la comprobación sistemática de los tipos y estructuras de entrada.
Estrategias de validación exhaustivas
1. Validación de clases de datos (Data Class)
from dataclasses import dataclass
from typing import List
import re
@dataclass
class User:
name: str
email: str
age: int
skills: List[str]
def __post_init__(self):
## Custom validation logic
if not re.match(r"[^@]+@[^@]+\.[^@]+", self.email):
raise ValueError("Invalid email format")
if self.age < 18:
raise ValueError("User must be 18 or older")
if len(self.skills) == 0:
raise ValueError("At least one skill is required")
## Example usage
try:
user = User(
name="LabEx Developer",
email="[email protected]",
age=25,
skills=["Python", "Data Science"]
)
except ValueError as e:
print(f"Validation Error: {e}")
2. Validación de modelos de Pydantic
from pydantic import BaseModel, validator, EmailStr
from typing import List
class AdvancedUser(BaseModel):
name: str
email: EmailStr
age: int
skills: List[str]
@validator('age')
def validate_age(cls, age):
if age < 18:
raise ValueError("Must be 18 or older")
return age
@validator('skills')
def validate_skills(cls, skills):
if len(skills) < 1:
raise ValueError("At least one skill required")
return skills
## Validation example
try:
user = AdvancedUser(
name="LabEx Developer",
email="[email protected]",
age=25,
skills=["Python", "Machine Learning"]
)
except ValueError as e:
print(f"Validation Error: {e}")
Comparación de técnicas de validación
Técnica |
Ventajas |
Desventajas |
Caso de uso |
Validación manual |
Control total |
Detallada |
Escenarios simples |
Clases de datos (Data Classes) |
Integradas en Python |
Validación limitada |
Datos estructurados |
Pydantic |
Exhaustiva |
Dependencia externa |
Validación compleja |
Diagrama de flujo de validación
graph TD
A[Input Data] --> B{Structural Check}
B --> |Pass| C{Type Check}
B --> |Fail| D[Reject Data]
C --> |Pass| E{Custom Validation}
C --> |Fail| F[Reject Data]
E --> |Pass| G[Accept Data]
E --> |Fail| H[Reject Data]
Patrones de validación avanzados
Decorador de validación personalizado
from functools import wraps
from typing import Callable, Any
def validate_types(*type_args, **type_kwargs):
def decorator(func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
## Validate positional arguments
for arg, expected_type in zip(args, type_args):
if not isinstance(arg, expected_type):
raise TypeError(f"Expected {expected_type}, got {type(arg)}")
## Validate keyword arguments
for key, value in kwargs.items():
if key in type_kwargs:
expected_type = type_kwargs[key]
if not isinstance(value, expected_type):
raise TypeError(f"Expected {expected_type} for {key}, got {type(value)}")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_types(str, int, name=str)
def create_profile(username: str, age: int, name: str):
return f"{name} (Age: {age})"
## Usage examples
try:
profile = create_profile("developer", 25, name="LabEx")
print(profile)
except TypeError as e:
print(f"Validation Error: {e}")
Mejores prácticas para la validación de tipos
- Utilizar las indicaciones de tipo (type hints) de manera consistente.
- Implementar una lógica de validación exhaustiva.
- Proporcionar mensajes de error claros.
- Equilibrar entre rigidez y flexibilidad.
- Elegir las técnicas de validación adecuadas.
Consideraciones de rendimiento
- Minimizar la complejidad de la validación.
- Utilizar bibliotecas de validación eficientes.
- Implementar validación perezosa (lazy validation) cuando sea posible.
- Realizar perfiles y optimizar la lógica de validación.
Al implementar una validación de tipos sólida, los desarrolladores pueden crear aplicaciones Python más confiables y autodocumentadas con una integridad de datos mejorada.