enum.verify: valida reglas de Enum en Python

Publicado el: 06/09/2026
Tempo de leitura: 6 minutos
Código Python validado con enum.verify

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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python que representa functools.Placeholder y argumentos posicionales
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    functools.Placeholder: argumentos flexibles en partial

    Aprende functools.Placeholder en Python 3.14 para crear llamadas parciales flexibles con argumentos posicionales abiertos.

    Ler mais

    Tempo de leitura: 6 minutos
    17/10/2026
    Código en una pantalla que representa t-strings en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    T-strings en Python 3.14: templates estructurados

    Aprende t-strings en Python 3.14, explora Template e Interpolation y crea renderizadores estructurados, extensibles y seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    16/10/2026
    CPU y módulos de memoria que representan shared_memory track en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    shared_memory track: controla el resource tracker

    Aprende shared_memory track en Python para controlar el resource tracker, la propiedad y la limpieza entre procesos.

    Ler mais

    Tempo de leitura: 5 minutos
    16/10/2026
    Unidad de almacenamiento de datos que representa compression.zstd en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: streaming y compresión segura

    Aprende compression.zstd en Python para comprimir archivos y datos con velocidad, streaming, diccionarios y límites seguros.

    Ler mais

    Tempo de leitura: 7 minutos
    15/10/2026
    Código en pantalla para diagnosticar procesos con sys.remote_exec en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sys.remote_exec: diagnostica procesos Python

    Aprende sys.remote_exec en Python para diagnosticar procesos activos con scripts controlados, permisos seguros y buenas prácticas.

    Ler mais

    Tempo de leitura: 7 minutos
    15/10/2026
    Código Python y configuración de variables de entorno con os.reload_environ
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    os.reload_environ: threads y variables de entorno

    Aprende os.reload_environ en Python para actualizar variables de entorno externas con validación, compatibilidad y precauciones de concurrencia.

    Ler mais

    Tempo de leitura: 5 minutos
    14/10/2026