enum.verify: valide regras de Enum no Python

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

enum.verify é um recurso da biblioteca padrão do Python usado para validar regras de uma enumeração no momento em que a classe é criada. Ele ajuda a detectar problemas antes que a enum seja usada em produção, como valores duplicados, lacunas inesperadas em sequências numéricas ou combinações inválidas em flags. Em sistemas que dependem de códigos estáveis, permissões, estados ou protocolos, essa validação reduz erros silenciosos e torna o contrato da enum mais explícito.

O recurso trabalha com o decorador verify() e com verificadores prontos como UNIQUE, CONTINUOUS e NAMED_FLAGS. Em vez de escrever testes manuais para cada classe, você declara a regra junto da própria enum. Se a regra for violada, o Python levanta um erro durante a definição da classe.

Por que validar enums

Enums são frequentemente usadas para representar estados, códigos de retorno, tipos de evento, níveis de acesso e categorias de domínio. O problema é que uma enum mal definida pode continuar funcionando por muito tempo. Dois nomes podem compartilhar o mesmo valor sem intenção, uma sequência pode pular números importantes ou uma flag composta pode usar bits sem nomes correspondentes.

Esses defeitos costumam aparecer apenas quando outro sistema consome os valores, quando um banco de dados espera uma faixa específica ou quando a serialização encontra aliases inesperados. enum.verify desloca essa falha para o início da aplicação, onde é mais simples diagnosticar.

Validando valores únicos com UNIQUE

from enum import Enum, verify, UNIQUE

@verify(UNIQUE)
class Status(Enum):
    PENDENTE = 1
    PROCESSANDO = 2
    CONCLUIDO = 3

Nesse exemplo, todos os valores são distintos. Se dois membros usarem o mesmo número, a criação da classe falha:

@verify(UNIQUE)
class Status(Enum):
    PENDENTE = 1
    PROCESSANDO = 2
    FINALIZADO = 2

Sem UNIQUE, FINALIZADO seria tratado como alias de PROCESSANDO. Aliases podem ser úteis para compatibilidade, mas devem ser deliberados. Em enums de protocolo, banco ou API, valores duplicados acidentais geram ambiguidade.

Quando aliases são aceitáveis

Nem todo alias é um erro. Durante uma migração, um nome antigo pode continuar existindo apontando para o novo valor. Nesse caso, não use UNIQUE ou mantenha a compatibilidade em uma camada externa. O ponto principal é tornar a decisão explícita.

Se aliases forem necessários temporariamente, documente o motivo, defina uma data de remoção e teste a serialização. Isso evita que clientes externos passem a depender do nome obsoleto.

Sequências contínuas com CONTINUOUS

from enum import IntEnum, verify, CONTINUOUS

@verify(CONTINUOUS)
class Prioridade(IntEnum):
    BAIXA = 1
    MEDIA = 2
    ALTA = 3

CONTINUOUS verifica se todos os valores inteiros entre o menor e o maior foram usados. Se a sequência saltar de 1 para 3, a classe é rejeitada. Isso é útil quando cada número representa uma posição contínua, um índice ou uma etapa de processo.

Não use essa regra quando lacunas fizerem parte do contrato. Códigos HTTP, por exemplo, não são contínuos. Em protocolos legados, intervalos podem estar reservados. A verificação correta depende do significado do domínio, não apenas da estética dos números.

Exemplo de lacuna detectada

@verify(CONTINUOUS)
class Etapa(IntEnum):
    INICIO = 1
    VALIDACAO = 2
    PUBLICACAO = 4

O valor 3 está ausente. Se isso for um erro, a validação impede a enum de existir. Se a lacuna for intencional, remova CONTINUOUS e documente o intervalo reservado.

Flags nomeadas com NAMED_FLAGS

from enum import Flag, verify, NAMED_FLAGS

@verify(NAMED_FLAGS)
class Permissao(Flag):
    LER = 1
    ESCREVER = 2
    EXCLUIR = 4
    ADMIN = LER | ESCREVER | EXCLUIR

NAMED_FLAGS verifica se aliases e combinações usam somente bits que também possuem nomes válidos. Isso é importante porque uma máscara composta pode incluir um bit desconhecido, criando permissões que não podem ser interpretadas corretamente.

Com flags, prefira potências de dois para os membros básicos. As combinações podem usar o operador |. Quando cada bit tem um nome claro, logs, depuração e auditoria ficam mais confiáveis.

Combinando verificações

from enum import IntEnum, verify, UNIQUE, CONTINUOUS

@verify(UNIQUE, CONTINUOUS)
class Nivel(IntEnum):
    INICIANTE = 1
    INTERMEDIARIO = 2
    AVANCADO = 3

O decorador aceita mais de uma regra. Nesse caso, a enum precisa ter valores únicos e contínuos. Combine verificações apenas quando ambas representarem o contrato real.

Erros na inicialização da aplicação

A validação acontece durante a criação da classe. Em muitos projetos, isso ocorre na importação do módulo. Portanto, uma enum inválida pode impedir a aplicação de iniciar. Esse comportamento é desejável para erros de contrato, mas deve ser considerado em ferramentas de plugin ou ambientes que carregam módulos dinamicamente.

Em aplicações críticas, cubra as enums com testes de importação e execute esses testes no pipeline de integração contínua. Assim, a falha aparece antes do deploy.

Enum, IntEnum e Flag

Enum cria membros simbólicos sem comportamento numérico implícito. IntEnum permite interoperabilidade com inteiros, o que pode ser necessário em bancos, bibliotecas antigas e protocolos. Flag representa combinações de bits.

Escolha o tipo mais restrito possível. Se o valor não precisa agir como inteiro, prefira Enum. Se diferentes permissões precisam ser combinadas, use Flag ou IntFlag. A validação com verify complementa essa escolha.

Integração com APIs e bancos

Ao persistir enums, decida se o banco armazenará o nome ou o valor. Nomes são mais legíveis, mas mudanças de nomenclatura exigem migração. Valores são compactos, porém precisam permanecer estáveis. UNIQUE ajuda a evitar colisões quando valores são persistidos.

Em APIs, serialize de forma consistente. Não exponha ora o nome, ora o número. Crie uma camada de conversão e valide entradas desconhecidas. O fato de a enum estar correta não elimina a necessidade de tratar dados externos inválidos.

Testando enums verificadas

def test_status_values():
    assert Status.PENDENTE.value == 1
    assert Status.CONCLUIDO.name == "CONCLUIDO"

def test_prioridades_continuas():
    valores = [item.value for item in Prioridade]
    assert valores == [1, 2, 3]

O decorador protege a definição, mas testes ainda são úteis para garantir valores públicos, serialização e compatibilidade. Se os números fazem parte de um contrato externo, trate mudanças como alterações de API.

Boas práticas

Use nomes claros, evite mudar valores já publicados, documente aliases intencionais, escolha verificadores de acordo com o domínio e mantenha as enums próximas da lógica que representam. Não use CONTINUOUS apenas porque uma sequência parece mais organizada. Não use UNIQUE quando aliases fazem parte de uma estratégia de compatibilidade conscientemente planejada.

Prefira membros básicos simples e combinações explícitas em flags. Para grandes catálogos controlados por terceiros, considere gerar a enum a partir de uma fonte oficial e validar o resultado em testes.

Na Academify, complemente o estudo com dicionários em Python, conjuntos em Python, classes em Python e dataclasses em Python. Consulte também a documentação oficial do módulo enum e a PEP 435, que descreve a inclusão de enums no Python.

Conclusão

enum.verify transforma regras implícitas em validações executáveis. Com UNIQUE, você evita aliases acidentais. Com CONTINUOUS, detecta lacunas indevidas. Com NAMED_FLAGS, protege máscaras de bits contra combinações sem nomes válidos. O resultado é uma enum mais previsível, fácil de auditar e segura para uso em APIs, bancos, permissões e fluxos de negócio.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código Python em um notebook para criar dataclasses dinâmicas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    make_dataclass decorator: transforme dataclasses

    Aprenda a usar o parâmetro decorator de make_dataclass para validar, registrar e transformar dataclasses dinâmicas no Python.

    Ler mais

    Tempo de leitura: 6 minutos
    23/10/2026
    Estrutura de código e XML para canonicalização com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: normalize XML no Python

    Aprenda ElementTree canonicalize no Python para comparar XML, gerar hashes estáveis e controlar namespaces, espaços e comentários.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Código de programação Python em uma tela
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    T-strings e templatelib: interpolação estruturada

    Aprenda t-strings e string.templatelib no Python para processar interpolações, criar renderizadores seguros e preservar dados estruturados.

    Ler mais

    Tempo de leitura: 6 minutos
    22/10/2026
    Banco SQLite e código Python para exportação seletiva com iterdump
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: crie dumps seletivos no Python

    Aprenda sqlite3.Connection.iterdump com filtro para gerar dumps seletivos, validar dependências e restaurar bancos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    21/10/2026
    Código e arquivos representando compressão de dados no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Zstandard rápido no Python

    Aprenda a usar compression.zstd no Python para comprimir e descomprimir dados com desempenho, streaming e segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    21/10/2026
    Arquivo de configuração e estrutura de código para ConfigParser no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ConfigParser: leia INI sem seção no Python

    Aprenda a ler arquivos INI sem cabeçalho usando ConfigParser, com validação, tipos, compatibilidade e escrita segura.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026