EnumDict é uma classe do módulo enum usada durante a criação de enumerações. Ela funciona como o namespace controlado que recebe os nomes definidos dentro do corpo de uma classe Enum. Embora muita gente nunca precise utilizá-la diretamente, compreender seu papel ajuda a criar metaclasses, extensões de EnumType, validações de membros e APIs declarativas mais previsíveis.
O que é EnumDict
Quando o Python executa o corpo de uma classe, ele usa um objeto de mapeamento como namespace temporário. Em classes comuns, normalmente é um dicionário. Para enumerações, a metaclasse precisa acompanhar ordem, aliases, nomes reservados e regras especiais. EnumDict existe para aplicar essas regras durante a definição.
Ela não é um substituto genérico para dict. Seu propósito está ligado ao processo de construção de enumerações e ao comportamento de EnumType.
Por que ela é útil
O principal caso de uso é criar uma metaclasse personalizada baseada em EnumType. Com isso, você pode interpretar valores declarados no corpo da enumeração, validar convenções, gerar metadados ou transformar entradas antes que a classe final seja criada.
Esse recurso é avançado. Para enumerações normais, continue usando Enum, IntEnum, StrEnum ou Flag. Use EnumDict quando o comportamento padrão não for suficiente e você realmente precisar controlar a fase de definição.
Exemplo conceitual
from enum import Enum, EnumType, EnumDict
class MinhaMetaEnum(EnumType):
@classmethod
def __prepare__(metacls, cls, bases, **kwds):
namespace = EnumDict(cls)
return namespace
class Status(Enum, metaclass=MinhaMetaEnum):
ATIVO = "ativo"
INATIVO = "inativo"
print(Status.ATIVO.value)O método __prepare__ escolhe o namespace usado durante a execução do corpo da classe. Ao retornar EnumDict, a metaclasse preserva as regras esperadas pelo sistema de enumerações.
Não use um dict comum sem motivo
Trocar EnumDict por um dicionário simples pode parecer funcionar em exemplos pequenos, mas pode quebrar detalhes importantes: ordem dos membros, nomes ignorados, aliases e validações internas. O erro mais perigoso é obter uma classe que parece correta, mas se comporta de forma diferente em casos extremos.
Validação de nomes
Uma metaclasse pode usar o namespace preparado para validar padrões de nomenclatura. Por exemplo, você pode exigir nomes em maiúsculas, bloquear prefixos internos ou impedir valores duplicados.
from enum import Enum, EnumType, EnumDict
class MetaMaiusculas(EnumType):
@classmethod
def __prepare__(metacls, cls, bases, **kwds):
return EnumDict(cls)
def __new__(metacls, cls, bases, classdict, **kwds):
for nome in classdict.member_names:
if nome != nome.upper():
raise ValueError(f"Membro inválido: {nome}")
return super().__new__(metacls, cls, bases, classdict, **kwds)
class Cor(Enum, metaclass=MetaMaiusculas):
VERMELHO = 1
AZUL = 2A validação acontece antes da classe final existir, o que torna o erro claro e imediato.
member_names
Versões recentes do Python expõem member_names no namespace da enumeração. Essa lista permite consultar os nomes dos membros na ordem em que foram declarados. Isso é útil para validações, geração de documentação e transformação controlada.
Não modifique essa estrutura sem entender o impacto. Ela participa do processo de construção da classe e alterações incorretas podem gerar membros inconsistentes.
Metadados declarativos
Outro uso possível é permitir que cada item carregue informações extras. Em vez de espalhar dicionários paralelos pelo projeto, você pode definir tuplas ou objetos diretamente na enumeração e interpretar esses valores na metaclasse.
from enum import Enum
class CodigoHTTP(Enum):
OK = (200, "Sucesso")
NAO_ENCONTRADO = (404, "Recurso ausente")
def __init__(self, codigo, descricao):
self.codigo = codigo
self.descricao = descricaoEsse exemplo não exige EnumDict, mas mostra o tipo de API declarativa que uma metaclasse personalizada pode expandir.
Aliases e duplicidade
Enumerações permitem aliases quando dois nomes recebem o mesmo valor, salvo quando regras adicionais são aplicadas. Uma metaclasse pode detectar essa situação e exigir unicidade. Antes de implementar sua própria checagem, avalie o decorador @unique, que resolve o caso mais comum de forma simples.
Compatibilidade
EnumDict é voltado a extensões avançadas e sua interface deve ser usada conforme a documentação da versão do Python em execução. Evite depender de atributos internos não documentados. Bibliotecas que suportam várias versões devem verificar disponibilidade e manter testes específicos.
import enum
EnumDict = getattr(enum, "EnumDict", None)
if EnumDict is None:
raise RuntimeError("EnumDict não está disponível nesta versão")Testes recomendados
Teste ordem de membros, aliases, herança, valores automáticos, StrEnum, IntEnum, serialização, comparação e mensagens de erro. Também teste nomes especiais como _ignore_, _missing_ e métodos definidos no corpo da enumeração.
Inclua testes de regressão para garantir que uma atualização do Python não altere silenciosamente o comportamento esperado.
Erros comuns
Os erros mais comuns são usar EnumDict como dicionário genérico, substituir o namespace por um dict comum, alterar estruturas internas, criar metaclasses sem testes e resolver com metaprogramação algo que poderia ser feito com @unique, auto() ou um método simples.
Quando evitar
Evite EnumDict quando você só precisa armazenar constantes, associar descrições ou validar valores na aplicação. Uma enumeração comum com propriedades costuma ser mais legível. Metaclasses aumentam a complexidade e dificultam manutenção por pessoas menos familiarizadas com o modelo de classes do Python.
Boas práticas
Mantenha a metaclasse pequena, documente as regras, produza erros claros, não dependa de detalhes privados, teste múltiplas versões e prefira recursos públicos do módulo enum. Se a extensão precisar transformar muitos dados, considere uma função de fábrica ou um decorador de classe.
Links úteis
Veja também enums em Python, decoradores em Python, orientação a objetos e type hints.
Consulte a documentação oficial do módulo enum e o modelo de dados do Python.
Conclusão
EnumDict é uma ferramenta especializada para quem precisa controlar a criação de enumerações. Ela permite preservar as regras do módulo enum enquanto uma metaclasse adiciona validações ou comportamento declarativo. Use apenas quando a necessidade justificar a complexidade e sempre acompanhe a implementação com testes claros.







