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 ValueError para 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

✅ 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! 🐍