Enums em Python: Guia Completo para Código Mais Limpo e Seguro

Tipos Enumerados (Enums) em Python: Guia Completo para Legibilidade e Segurança

Enums, ou tipos enumerados, são estruturas de dados amplamente utilizadas em diversas linguagens de programação, como C, C++ e Java. Eles desempenham um papel crucial na criação de código com maior segurança de tipo e clareza.

Embora o Python não tenha oferecido suporte nativo a enums em suas versões anteriores, a partir da versão 3.4, essa funcionalidade foi introduzida. Este artigo tem como objetivo fornecer um guia abrangente sobre a criação, utilização e os benefícios que os enums trazem para a legibilidade do seu código Python.

O que São Enums e Qual a Sua Finalidade?

Uma enumeração, ou enum, é um tipo de dado que se define pelo conjunto de valores específicos que ele pode assumir. Esses valores são conhecidos como membros. Os enums permitem restringir os valores possíveis que uma variável pode ter, promovendo assim a segurança de tipo e melhorando significativamente a clareza do código.

Termos Importantes para Entender Enums

Antes de aprofundarmos o tema, é importante esclarecer alguns termos que serão usados com frequência ao longo deste artigo: membros e valores.

  • Membros: São as constantes nomeadas que compõem o conjunto de valores possíveis para um enum. Por exemplo, um enum chamado DiasDaSemana poderia ter como membros: Domingo, Segunda, Terça, e assim por diante.
  • Valores: São os valores internos que representam cada membro do enum, permitindo comparações. No mesmo enum DiasDaSemana, Domingo poderia ter o valor 0, Segunda o valor 1, e assim sucessivamente.

Agora, vamos explorar como os enums podem aprimorar seu código.

Como os Enums Melhoram Seu Código?

A utilização de enums leva a um código mais legível, menos propenso a erros e com maior clareza. Veja alguns dos motivos pelos quais você deve considerar usar enums:

  • Enums permitem definir de forma explícita os valores esperados para um argumento de variável ou função, deixando suas intenções claras para quem lê seu código.
  • Eles tornam o código auto-documentado, eliminando a necessidade de comentários extensos ou documentação para especificar os valores aceitáveis por uma função.
  • IDEs podem utilizar enums para destacar erros quando valores incorretos são passados, além de fornecer suporte para autocompletar.
  • O resultado é um código mais robusto, com menor probabilidade de erros em tempo de execução.

A seguir, vamos explorar como criar enums em Python.

Como Criar Enums em Python

O Python, apesar de não ter suporte nativo a enums, fornece o módulo enum em sua biblioteca padrão. Vamos utilizá-lo neste guia. Existem duas abordagens para criar enums: utilizando classes ou a API funcional, e ambas serão abordadas nesta seção.

Pré-requisitos

Para seguir este guia, você precisará ter o Python 3.4 ou superior instalado, pois é a versão que introduziu o módulo enum. Caso ainda não tenha, procure um guia de instalação para sua plataforma.

Além disso, é necessário um conhecimento básico de Python, incluindo conceitos como programação orientada a objetos, classes e herança.

#1. O Método de Classe

A primeira forma de criar um enum é através do uso de classes. Primeiramente, você importa a classe Enum do módulo enum. Em seguida, define sua enumeração criando uma nova classe que herda da classe Enum.

from enum import Enum

class Direcao(Enum):
    NORTE = 0
    LESTE = 1
    SUL = 2
    OESTE = 3

É possível atribuir qualquer valor desejado aos membros do enum. Por exemplo, em vez de usar 0, 1, 2 e 3 para as direções, podemos atribuir os ângulos correspondentes: 0, 90, 180 e 270 graus.

from enum import Enum

class Direcao(Enum):
    NORTE = 0
    LESTE = 90
    SUL = 180
    OESTE = 270

Outra maneira mais concisa é usar a função range para gerar os valores. Veja o exemplo:

from enum import Enum

class Direcao(Enum):
    NORTE, LESTE, SUL, OESTE = range(0, 360, 90)

Aqui, a função range gera uma sequência de valores (0, 90, 180, 270), que são então atribuídos aos membros do enum através de desempacotamento. Se você quiser saber mais sobre desempacotamento de tuplas, procure material sobre tuplas em Python.

As classes Enum são abstratas e, portanto, não devem ser instanciadas. Em vez disso, seus membros são acessados diretamente através de suas propriedades.

#2. O Método da Função

O método da função oferece uma alternativa à abordagem de subclasse.

from enum import Enum

Direcao = Enum("Direcao", ["NORTE", "LESTE", "SUL", "OESTE"])

Neste exemplo, criamos um enum chamado Direcao. Os membros são definidos no segundo argumento. Por padrão, eles recebem valores a partir de 1 (NORTE = 1, LESTE = 2, etc). Isso acontece para que nenhum valor seja falso (zero).

É possível atribuir valores específicos aos membros usando uma lista de tuplas. Cada tupla contém o nome do membro e seu valor correspondente.

from enum import Enum

Direcao = Enum(
    name="Direcao",
    values=[
        ("NORTE", "n"),
        ("LESTE", "e"),
        ("SUL", "s"),
        ("OESTE", "w"),
    ]
)

Observe que neste exemplo, foram usadas strings em vez de números para os valores. Isso demonstra a flexibilidade dos enums em Python, que aceitam strings e números como valores.

Como Utilizar Enums

Na seção anterior, exploramos a criação de enums e a atribuição de valores. Agora, vamos analisar como acessar e atribuir membros, além de verificar a igualdade entre eles.

Como Acessar Membros

Existem diversas formas de acessar os membros de um enum, incluindo a sintaxe de ponto, parênteses e colchetes. Veja o exemplo:

from enum import Enum

# Criação de um enum
class Dia(Enum):
    DOMINGO, SEGUNDA, TERCA, QUARTA, QUINTA, SEXTA, SABADO = range(1, 8)

# Acessando membros do enum
# 1. Usando sintaxe de ponto
print(Dia.DOMINGO)

# 2. Usando colchetes
print(Dia["SEGUNDA"])

# 3. Usando parênteses
print(Dia(3))

Depois de acessar um membro, ele pode ser armazenado em uma variável. Lembre-se que ao acessar um membro, você obtém uma referência ao objeto membro, não o seu valor ou nome diretamente.

Acessando o Nome e o Valor

Como mencionado anteriormente, ao acessar um membro, você obtém uma referência ao objeto membro. Caso necessite do nome ou do valor, você pode acessar as propriedades name e value.

print(Dia.DOMINGO.name, Dia.DOMINGO.value)

Verificando a Igualdade

Ao atribuir um membro a uma variável, você cria uma referência ao objeto membro. Portanto, para verificar se uma variável se refere a um membro específico, use o operador is, que compara as referências dos objetos.

Veja o exemplo:

hoje = Dia.QUARTA

if hoje is Dia.SEGUNDA:
    print("É segunda, :(")

if hoje is Dia.QUARTA:
    print("Feliz Quarta")

Alternativamente, pode-se usar o operador ==, que, nas superclasses do Enum, é um wrapper para o operador is, através de sobrecarga de operador. Veja o artigo sobre Métodos Mágicos para mais detalhes. Um exemplo:

hoje = Dia.QUARTA

if hoje == Dia.SEGUNDA:
    print("É segunda, :(")

if hoje == Dia.QUARTA:
    print("Feliz Quarta")

Reiterando, comparações em enums verificam a identidade do objeto, não os valores.

Considerações Finais

Este artigo abordou o conceito de enums, suas vantagens, e como criá-los utilizando classes e a API funcional. Também foi demonstrado como usar enums, acessar seus valores e realizar comparações. Se você tiver interesse, procure outros materiais sobre enums, como o artigo sobre enums em TypeScript, mencionado no artigo original.