Enumerações (Enums) são um recurso poderoso da linguagem Python que permite definir conjuntos fixos de valores nomeados. Desde sua introdução no Python 3.4 através da PEP 435, o módulo enum se tornou essencial para escrever código mais expressivo, seguro e fácil de manter.
Neste guia completo, você aprenderá desde os conceitos básicos até técnicas avançadas de Enum em Python, com exemplos práticos que você pode aplicar imediatamente nos seus projetos.
🔷 O Que São Enumerações?
Uma enumeração é um tipo de dado que consiste em um conjunto fixo de valores nomeados chamados membros. Em vez de usar strings soltas ou números mágicos espalhados pelo código, você define um Enum que centraliza e dá significado a esses valores.
Por exemplo, em vez de usar strings como "segunda", "terca" que podem ter erros de digitação, você pode criar:
from enum import Enum
class DiaSemana(Enum):
SEGUNDA = 1
TERCA = 2
QUARTA = 3
QUINTA = 4
SEXTA = 5
SABADO = 6
DOMINGO = 7
Agora, ao invés de comparar strings propensas a erros, você usa DiaSemana.SEGUNDA, garantindo que apenas valores válidos sejam utilizados.
📖 Por Que Usar Enum?
Enumerações trazem diversos benefícios para o seu código:
- Legibilidade: nomes significativos substituem números mágicos ou strings soltas
- Segurança: previne erros de digitação e valores inválidos
- Manutenibilidade: mudanças centralizadas em um único local
- Autodocumentação: o código expressa claramente suas intenções
- Iteração: você pode percorrer todos os membros facilmente
- Comparação: membros podem ser comparados por identidade
Segundo a documentação oficial do Python, Enums são ideais para representar valores fixos como estados, categorias, direções, cores e qualquer conjunto finito de opções.
🚀 Criando Seu Primeiro Enum
Vamos criar um Enum para representar o status de um pedido em um sistema de e-commerce:
from enum import Enum
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 3
ENTREGUE = 4
CANCELADO = 5
Acessando membros
print(StatusPedido.PENDENTE) # StatusPedido.PENDENTE
print(StatusPedido.PENDENTE.name) # 'PENDENTE'
print(StatusPedido.PENDENTE.value) # 1
Cada membro do Enum possui dois atributos principais:
.name: retorna o nome do membro como string.value: retorna o valor atribuído ao membro
Você também pode criar Enums usando a API Funcional, que é útil para Enums simples:
from enum import Enum
Cor = Enum('Cor', ['VERMELHO', 'AZUL', 'VERDE'])
print(Cor.VERMELHO) # Cor.VERMELHO
print(list(Cor)) # [Cor.VERMELHO, Cor.AZUL, Cor.VERDE]
🎯 Acessando Membros por Nome e Valor
Python permite acessar membros tanto pelo nome quanto pelo valor:
from enum import Enum
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
Acesso por nome
status = StatusPedido['PENDENTE']
print(status) # StatusPedido.PENDENTE
Acesso por valor
status = StatusPedido(2)
print(status) # StatusPedido.CONFIRMADO
Essa flexibilidade é extremamente útil ao integrar com bancos de dados ou APIs que retornam valores numéricos.
🔄 Iterando Sobre Enums
Enums são iteráveis, permitindo percorrer todos os seus membros facilmente:
for status in StatusPedido:
print(f"{status.name} = {status.value}")
Saída:
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 3
ENTREGUE = 4
CANCELADO = 5
Isso é particularmente útil para popular comboboxes, gerar relatórios ou validar entradas.
🔧 Enum com auto()
O auto() gera valores automaticamente para você, evitando a necessidade de numerar manualmente cada membro:
from enum import Enum, auto
class StatusPedido(Enum):
PENDENTE = auto()
CONFIRMADO = auto()
ENVIADO = auto()
ENTREGUE = auto()
CANCELADO = auto()
print(list(StatusPedido))
[StatusPedido.PENDENTE, StatusPedido.CONFIRMADO, ...]
Verificando os valores gerados
for status in StatusPedido:
print(f"{status.name} = {status.value}")
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 3
ENTREGUE = 4
CANCELADO = 5
Por padrão, auto() começa em 1 e incrementa de 1 em 1, mas você pode personalizar esse comportamento sobrescrevendo o método _generate_next_value_.
🏷️ IntEnum: Enum com Comportamento de Inteiro
IntEnum é uma subclasse de Enum que também herda de int, permitindo que os membros se comportem como inteiros:
from enum import IntEnum
class Prioridade(IntEnum):
BAIXA = 1
MEDIA = 2
ALTA = 3
Pode ser usado como inteiro
print(Prioridade.ALTA > Prioridade.MEDIA) # True
print(Prioridade.ALTA + Prioridade.BAIXA) # 4
Pode substituir inteiros diretamente
def processar_ticket(prioridade: Prioridade):
if prioridade >= Prioridade.ALTA:
print("Prioridade alta! Processar imediatamente.")
processar_ticket(3) # Funciona! IntEnum aceita comparação com int
IntEnum é perfeito para quando você precisa que os membros possam ser usados em contextos que esperam inteiros, como índices de lista ou parâmetros de funções que exigem números.
🚩 Flag: Enum para Combinar Valores
Flag é ideal para representar combinações de opções usando operações bit a bit:
from enum import Flag, auto
class Permissao(Flag):
LER = auto()
ESCREVER = auto()
EXECUTAR = auto()
DELETAR = auto()
Combinando permissões
permissao_admin = Permissao.LER | Permissao.ESCREVER | Permissao.EXECUTAR | Permissao.DELETAR
permissao_usuario = Permissao.LER | Permissao.ESCREVER
Verificando permissões
if Permissao.LER in permissao_usuario:
print("Usuário pode ler")
if Permissao.DELETAR not in permissao_usuario:
print("Usuário NÃO pode deletar")
Verificando membros
print(Permissao.LER) # Permissao.LER
print(Permissao.LER.value) # 1 (bits: 0001)
Flag é extremamente útil para sistemas de permissões, configurações de features, filtros e qualquer cenário onde múltiplas opções podem ser ativadas simultaneamente.
🧩 StrEnum: Enum com Comportamento de String
StrEnum (disponível desde Python 3.11) combina Enum com str:
from enum import StrEnum
class Cor(StrEnum):
VERMELHO = 'vermelho'
AZUL = 'azul'
VERDE = 'verde'
Pode ser usado como string
print(Cor.VERMELHO.upper()) # 'VERMELHO'
print(f"A cor é {Cor.AZUL}") # 'A cor é azul'
print(Cor.VERMELHO in 'vermelho escuro') # True
StrEnum é perfeito para integrar com bancos de dados, APIs REST e arquivos de configuração onde strings são o formato padrão de troca de dados.
🧠 Métodos e Propriedades em Enums
Enums podem ter métodos e propriedades personalizados, tornando-os ainda mais poderosos:
from enum import Enum
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 3
ENTREGUE = 4
CANCELADO = 5
@property
def descricao(self):
descricoes = {
1: 'Aguardando confirmação',
2: 'Pagamento confirmado',
3: 'Saiu para entrega',
4: 'Entregue ao cliente',
5: 'Pedido cancelado',
}
return descricoes[self.value]
def is_final(self):
return self in (StatusPedido.ENTREGUE, StatusPedido.CANCELADO)
Usando métodos e propriedades
status = StatusPedido.ENVIADO
print(status.descricao) # 'Saiu para entrega'
print(status.is_final()) # False
status = StatusPedido.ENTREGUE
print(status.is_final()) # True
print(status.descricao) # 'Entregue ao cliente'
Essa abordagem mantém a lógica relacionada ao Enum centralizada, seguindo o princípio da coesão e facilitando a manutenção.
🔍 Comparação e Identidade
Membros de Enum são singletons, o que significa que há apenas uma instância de cada membro na memória:
from enum import Enum
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
Comparação por identidade (recomendada)
print(StatusPedido.PENDENTE is StatusPedido.PENDENTE) # True
Comparação por igualdade
print(StatusPedido.PENDENTE == StatusPedido.PENDENTE) # True
print(StatusPedido.PENDENTE == StatusPedido.CONFIRMADO) # False
Comparação com valor (NÃO recomendado - funciona apenas por acaso)
print(StatusPedido.PENDENTE == 1) # False! (Exceto para IntEnum)
Sempre use is ou == para comparar membros do mesmo Enum. Evite comparar diretamente com valores, a menos que esteja usando IntEnum.
🛡️ Valores Únicos e @unique
Por padrão, Python permite valores duplicados em Enums (os nomes duplicados se tornam aliases). Use o decorador @unique para garantir que todos os valores sejam únicos:
from enum import Enum, unique
@unique
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 2 # Isso lançaria ValueError!
ENVIADO = 3
Valores duplicados são permitidos sem @unique
class CorSemUnique(Enum):
VERMELHO = 1
VERMELHO_ESCURO = 1 # Alias para VERMELHO
print(CorSemUnique(1)) # CorSemUnique.VERMELHO (o primeiro é o principal)
Use @unique sempre que a semântica do seu Enum exigir que cada valor seja único. Isso previne bugs sutis causados por aliases acidentais.
📋 Aliases em Enums
Aliases são nomes diferentes que apontam para o mesmo valor. Eles podem ser úteis para fornecer nomes alternativos:
from enum import Enum
class Cor(Enum):
VERMELHO = 1
RED = 1 # Alias em inglês
AZUL = 2
BLUE = 2
print(Cor.VERMELHO) # Cor.VERMELHO
print(Cor.RED) # Cor.VERMELHO (alias)
print(Cor(1)) # Cor.VERMELHO (o primeiro nome é o principal)
Listar apenas membros únicos (sem aliases)
print(list(Cor))
[Cor.VERMELHO, Cor.AZUL]
Aliases são especialmente úteis para manter compatibilidade com sistemas legados ou fornecer nomes em múltiplos idiomas.
💡 Boas Práticas com Enums
- Sempre use nomes em MAIÚSCULAS: por convenção, membros de Enum têm nomes em letras maiúsculas
- Use auto() quando possível: evita erros de numeração manual
- Prefira @unique: garante que não haja valores duplicados acidentalmente
- Use Enum em vez de strings ou ints soltos: para qualquer conjunto fixo de opções
- Combine com Type Hints: tipagem estática + Enums = código extremamente seguro
- Trate valores desconhecidos: ao receber dados externos, use
try/except ValueErrorpara capturar valores inválidos
⚠️ Tratamento de Erros com Enums
Ao receber valores externos (de APIs, bancos de dados ou formulários), é crucial tratar entradas inválidas:
from enum import Enum
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 3
ENTREGUE = 4
CANCELADO = 5
def obter_status(codigo: int):
try:
return StatusPedido(codigo)
except ValueError:
return None # Ou lançar uma exceção personalizada
Testando
print(obter_status(3)) # StatusPedido.ENVIADO
print(obter_status(99)) # None
Essa técnica se integra perfeitamente com o sistema de tratamento de erros em Python, garantindo que seu código lide graciosamente com entradas inesperadas.
🌐 Enums e Bancos de Dados
Enums são excelentes para representar colunas com valores fixos em bancos de dados. Veja como integrar com SQLAlchemy, por exemplo:
from enum import Enum
import sqlalchemy as sa
from sqlalchemy.orm import declarative_base, Mapped, mapped_column
class StatusPedido(Enum):
PENDENTE = 1
CONFIRMADO = 2
ENVIADO = 3
ENTREGUE = 4
CANCELADO = 5
Base = declarative_base()
class Pedido(Base):
tablename = 'pedidos'
id: Mapped[int] = mapped_column(primary_key=True)
status: Mapped[StatusPedido] = mapped_column(sa.Enum(StatusPedido))
Isso garante integridade referencial a nível de aplicação e banco de dados simultaneamente.
📦 Enums no Mundo Real
Enums são amplamente utilizados em projetos Python reais. Grandes frameworks como Django usam Enums extensivamente em seus modelos e configurações. O HOWTO oficial de Enum mostra exemplos avançados com OrderedEnum e outros padrões.
Aqui está um exemplo mais complexo de um sistema de logs com níveis:
from enum import IntEnum
from datetime import datetime
class NivelLog(IntEnum):
DEBUG = 10
INFO = 20
WARNING = 30
ERROR = 40
CRITICAL = 50
def formatar(self, mensagem: str) -> str:
timestamp = datetime.now().isoformat()
return f"[{timestamp}] [{self.name}] {mensagem}"
Uso
log = NivelLog.INFO.formatar("Sistema iniciado com sucesso")
print(log)
[2026-05-22T09:00:00] [INFO] Sistema iniciado com sucesso
📖 Leitura Recomendada
- Documentação oficial do módulo enum - A referência definitiva
- Enum HOWTO - Guia prático oficial
- PEP 435 - A especificação original dos Enums em Python
- Real Python: Python Enum - Tutorial completo
- Enum.auto() - Documentação sobre valores automáticos
- IntEnum - Enum com comportamento de inteiro
- Flag - Enum para combinações bit a bit
- Glossário Python: Enum - Definição no glossário oficial
✅ Conclusão
Enumerações em Python são muito mais do que simples listas de constantes. Elas fornecem uma maneira elegante e segura de representar conjuntos fixos de valores, tornando seu código mais legível, fácil de manter e menos propenso a erros.
Desde o básico com Enum e auto() até variantes poderosas como IntEnum, Flag e StrEnum, o módulo enum oferece ferramentas para praticamente qualquer cenário.
Agora que você domina Enums em Python, comece a aplicá-los nos seus projetos. Substitua aquelas strings soltas e números mágicos por enumerações bem definidas. Seu código (e seus colegas de equipe) vão agradecer! 🐍