enum.verify es una herramienta de la biblioteca estándar de Python que valida reglas de una enumeración cuando se crea la clase. Permite detectar valores duplicados, huecos inesperados en secuencias numéricas y combinaciones inválidas de flags antes de que esos errores lleguen a producción. Resulta especialmente útil cuando las enums representan códigos persistentes, estados de una API, permisos, etapas de un flujo o valores de un protocolo.
La función se usa mediante el decorador verify() y verificadores incluidos como UNIQUE, CONTINUOUS y NAMED_FLAGS. En lugar de depender únicamente de pruebas separadas, la regla queda declarada junto a la propia enum. Si no se cumple, Python genera un error durante la definición de la clase.
Por qué validar enumeraciones
Una enum puede convertirse en un contrato público. Dos nombres con el mismo valor pueden crear un alias accidental. Un número ausente puede romper un sistema externo que espera una secuencia completa. Una máscara compuesta puede incluir un bit que no tiene nombre y que resulta difícil de auditar.
Estos problemas suelen permanecer ocultos porque la clase continúa funcionando en operaciones comunes. La validación desplaza el fallo al inicio de la aplicación o a la fase de pruebas, donde es más sencillo encontrar la causa.
Valores únicos con UNIQUE
from enum import Enum, verify, UNIQUE
@verify(UNIQUE)
class Estado(Enum):
PENDIENTE = 1
PROCESANDO = 2
COMPLETADO = 3
Todos los miembros tienen valores diferentes. Si dos nombres comparten el mismo número, la creación de la clase falla. Sin esta verificación, el segundo nombre normalmente se convertiría en un alias del primero.
@verify(UNIQUE)
class Estado(Enum):
PENDIENTE = 1
PROCESANDO = 2
FINALIZADO = 2
Los aliases no siempre son incorrectos. Pueden mantener compatibilidad durante una migración. Sin embargo, deben ser intencionales, documentados y probados. En APIs y datos persistidos, un alias accidental crea ambigüedad en la serialización, los logs y las comparaciones.
Cuándo aceptar aliases
Un proyecto puede conservar un nombre antiguo para no romper clientes existentes. En ese caso, no uses UNIQUE o coloca la compatibilidad en una capa de conversión. Registra el motivo del alias, su periodo de soporte y el nombre canónico que debe aparecer en nuevas respuestas.
Muchas veces es más limpio aceptar el texto antiguo en un parser y convertirlo al miembro nuevo. Así, el modelo interno continúa siendo estricto.
Secuencias continuas con CONTINUOUS
from enum import IntEnum, verify, CONTINUOUS
@verify(CONTINUOUS)
class Prioridad(IntEnum):
BAJA = 1
MEDIA = 2
ALTA = 3
CONTINUOUS comprueba que todos los enteros entre el valor mínimo y el máximo están presentes. Una secuencia con 1, 2 y 4 falla porque falta el 3. La regla es útil para niveles ordenados, etapas contiguas, índices o rangos compactos de un protocolo.
No debe aplicarse cuando los huecos forman parte del contrato. Los códigos HTTP, por ejemplo, no son continuos. Algunos sistemas reservan intervalos para extensiones futuras. La validación debe reflejar el significado del dominio, no solo una preferencia estética.
Ejemplo de hueco detectado
@verify(CONTINUOUS)
class Etapa(IntEnum):
INICIO = 1
VALIDACION = 2
PUBLICACION = 4
Si el valor 3 se omitió por error, la clase falla inmediatamente. Si el hueco está reservado, elimina la regla y documenta el intervalo para evitar correcciones equivocadas en el futuro.
Flags con nombres mediante NAMED_FLAGS
from enum import Flag, verify, NAMED_FLAGS
@verify(NAMED_FLAGS)
class Permiso(Flag):
LEER = 1
ESCRIBIR = 2
ELIMINAR = 4
ADMIN = LEER | ESCRIBIR | ELIMINAR
NAMED_FLAGS valida que los aliases y las máscaras compuestas utilicen bits representados por miembros con nombre. Una combinación con un bit desconocido puede otorgar una capacidad que la aplicación no sabe describir correctamente.
Para los miembros básicos, utiliza potencias de dos. Construye combinaciones con el operador |. De esta manera, los logs, las auditorías y las comprobaciones de permisos son más legibles.
Combinar verificaciones
from enum import IntEnum, verify, UNIQUE, CONTINUOUS
@verify(UNIQUE, CONTINUOUS)
class Nivel(IntEnum):
PRINCIPIANTE = 1
INTERMEDIO = 2
AVANZADO = 3
El decorador acepta varias reglas. En este caso, los valores deben ser únicos y continuos. Combina verificaciones solo cuando cada una exprese un requisito real. Una regla demasiado estricta puede dificultar extensiones legítimas.
Fallos durante la importación
La validación ocurre al crear la clase, normalmente durante la importación del módulo. Por eso, una enum inválida puede impedir el inicio de la aplicación. Para errores de contrato, este comportamiento rápido es positivo. En sistemas de plugins o carga dinámica, conviene capturar y registrar el módulo responsable.
Incluye pruebas de importación en la integración continua. Son especialmente útiles cuando las enums se generan automáticamente o se modifican con frecuencia.
Elegir Enum, IntEnum y Flag
Enum ofrece miembros simbólicos sin comportamiento entero implícito. IntEnum facilita la interoperabilidad con sistemas numéricos. Flag representa combinaciones de bits. Elige el tipo más limitado que satisfaga la integración.
Si no necesitas comparar el miembro con enteros, prefiere Enum. Si un protocolo o sistema heredado exige números, usa IntEnum con cuidado. Para permisos combinables, usa Flag o IntFlag. verify refuerza estas decisiones, pero no sustituye un buen modelado.
APIs y bases de datos
Al persistir una enum, decide si guardarás el nombre o el valor. Los nombres son legibles, pero renombrarlos exige una migración. Los valores son compactos, aunque deben permanecer estables después de publicarse. UNIQUE evita colisiones accidentales en códigos almacenados.
En una API, serializa siempre de la misma forma. No devuelvas el nombre en un endpoint y el número en otro sin un contrato claro. Valida entradas desconocidas y convierte datos externos mediante una capa explícita.
Pruebas de enums verificadas
def test_contrato_estado():
assert Estado.PENDIENTE.value == 1
assert Estado.COMPLETADO.name == "COMPLETADO"
def test_prioridades_continuas():
assert [item.value for item in Prioridad] == [1, 2, 3]
El decorador valida la estructura, mientras las pruebas protegen valores públicos, serialización, parsing y compatibilidad. Si otros sistemas almacenan los números, cualquier cambio debe considerarse una modificación de API.
Estrategia de migración
Antes de añadir verificadores a un proyecto existente, revisa aliases y huecos. Algunos valores extraños pueden ser parte de un contrato antiguo. Documenta el comportamiento actual, añade pruebas y decide cuáles irregularidades son errores y cuáles deben mantenerse.
Para renombrar un miembro, acepta temporalmente el nombre anterior en la entrada, migra los datos persistidos y utiliza únicamente el nombre canónico en nuevas salidas.
Buenas prácticas
Usa nombres descriptivos, no reutilices valores ya publicados, documenta huecos intencionales y conserva las enums cerca de la lógica del dominio. Mantén simples los flags básicos y crea combinaciones con nombre para conjuntos de permisos habituales.
En catálogos grandes administrados por una autoridad externa, genera la enum desde la fuente oficial y valida el resultado en CI. Guarda también la versión de la fuente para revisar cambios.
Recursos relacionados
Continúa con los artículos de Academify sobre diccionarios en Python, conjuntos en Python, clases en Python y dataclasses en Python. Consulta también la documentación oficial de enum y la PEP 435.
Conclusión
enum.verify convierte supuestos implícitos en comprobaciones ejecutables. UNIQUE evita aliases accidentales, CONTINUOUS detecta huecos numéricos no deseados y NAMED_FLAGS protege las máscaras contra bits sin nombre. Aplicadas según el dominio, estas reglas producen contratos más seguros para APIs, bases de datos, permisos, flujos y protocolos.







