Domine Python Attrs: Crie Data Classes Avançadas com Exemplos Práticos

O pacote Python Attrs permite criar data classes avançadas usando anotações simples. Claro, o Python tem seu próprio módulo nativo de data classes, mas o pacote attrs oferece alguns recursos extras que você pode gostar!
Instalar attrs
O pacote attrs não faz parte da biblioteca base, então você precisará instalá-lo com o comando pip install ou algo similar, como Pipenv. Você provavelmente também quer criar um ambiente virtual, para não interferir com outros projetos que você tem. O pacote se chama attrs, então instalá-lo será assim:
$ pip install attrs # ou com pipenv: $ pipenv install attrs
Attrs vs data classes
Os autores do attrs de fato trabalharam no PEP que introduziu data classes no Python. As data classes nativas do Python são intencionalmente mantidas mais simples e fáceis de entender, enquanto attrs oferece a gama completa de recursos que você pode querer!
Algumas razões para escolher attrs do Python em vez das data classes embutidas:
- Você está usando uma versão do Python anterior a 3.7. Attrs cobre você desde que suporta todas as versões mainstream do Python, incluindo CPython 2.7 e PyPy.
- Você quer mais recursos: attrs oferece validadores e conversores
- Você quer desempenho ideal e uso mínimo de memória usando classes com slots do attrs
Um exemplo básico de Python attrs
Vamos ver um exemplo bem básico primeiro:
import attr
@attr.s
class Person(object):
name = attr.ib(default='John')
surname = attr.ib(default='Doe')
age = attr.ib(init=False)
p = Person()
print(p)
p = Person('Bill', 'Gates')
p.age = 60
print(p)
# Saída:
# Person(name='John', surname='Doe', age=NOTHING)
# Person(name='Bill', surname='Gates', age=60)
Algumas observações:
- A sintaxe é menos elegante e mais verbosa que a de data classes, mas você obtém recursos extras em troca.
- Semelhante a data classes, você obtém uma representação bem formatada dos seus dados quando imprime.
- O pacote attrs usa nomes inteligentemente escolhidos como
attr.ib, então você só precisa importarattr. Você pode, alternativamente, importar os nomes completos. Por exemplo, comfrom attr import attrib, attrs, e usar esses nomes em vez disso. A funcionalidade é a mesma.
Agora vamos ver os recursos mais importantes que este pacote oferece sobre data classes regulares: validadores e conversores.
Exemplo de validador Python attrs
Você pode adicionar validadores às suas data classes attrs de duas formas:
- Usando um decorador
- Fornecendo uma função chamável
Vou demonstrar o método de função chamável aqui primeiro. Attrs oferece vários validadores prontos, dos quais usaremos o validador instance_of no exemplo a seguir:
>> @attr.s
... class C(object):
... x = attr.ib(validator=attr.validators.instance_of(int))
>>> C(42)
C(x=42)
>>> C("a string")
Traceback (most recent call last):
...
TypeError: ("'x' must be <type 'int'> (got 'a string' that is a <type 'str'>).", ...
Como tentamos criar um objeto C com um valor string para x, o validador instance_of lança um erro porque requer um tipo int em vez de string.
Vamos agora definir nosso próprio validador:
import attr
@attr.s
class DividableByTwo(object):
x = attr.ib()
@x.validator
def check(self, attribute, value):
if value % 2 != 0:
raise ValueError(f'{value} não é divisível por 2')
print(DividableByTwo(60))
print(DividableByTwo(11))
# A saída será algo como:
# DividableByTwo(x=60)
# ...
# ValueError: 11 não é divisível por 2
Exemplo de conversor Python attrs
Um conversor pega o valor que é definido e o converte automaticamente. Você pode usar isso para todo tipo de propósito. Um exemplo é converter automaticamente um valor para int. Novamente, vamos começar usando uma função chamável, neste caso simplesmente usamos a função int() do Python:
import attr
@attr.s
class C(object):
x = attr.ib(converter=int)
c = C("1")
print(c)
# Saída:
# C(x=1)
Nossa entrada (a string "1") foi convertida para inteiro automaticamente. Como conversores são executados antes dos validadores, você pode validar o valor final após a conversão. Ex.: você poderia combinar os dois exemplos acima para primeiro converter qualquer entrada para int, e depois verificar se o valor é divisível por dois.
Usando slots com Python attrs
Finalmente, você pode dizer ao attrs para usar classes com slots. Classes com slots têm algumas vantagens sobre classes regulares:
- Elas têm uma pegada de memória pequena
- Elas são mais rápidas
Em resumo, com uma classe com slots você declara explicitamente quais atributos de instância espera que seus objetos tenham. Dessa forma, o Python pode pular algumas verificações e tal, resultando em menos uso de memória e leves aumentos de velocidade. Você pode encontrar mais detalhes na documentação do attrs aqui.
No entanto, classes com slots vêm com ressalvas também, especialmente quando você as cria manualmente. Felizmente, attrs nos oferece uma maneira simples de habilitar o recurso:
import attr
@attr.s(slots=True)
class YourClassName:
...
Continue aprendendo
- Nosso artigo sobre data classes Python
- Nosso tutorial sobre classes e objetos Python
- Para mais exemplos, confira a página de exemplos do attrs
python
- Dominando Tipos de Dados em Python: Guia Prático
- Dominando o Método strip() do Python: Guia Completo e Exemplos Práticos
- Domine o str.count() do Python: Como Contar Caracteres e Substrings com Exemplos
- Função round() em Python Explicada com Exemplos Práticos
- Dominando a Função map() do Python: Sintaxe, Exemplos e Boas Práticas
- Python timeit(): Medindo Tempo de Execução com Exemplos Práticos
- Counter do Python em collections: Contagem Eficiente, Atualização e Operações Aritméticas
- Python time.sleep(): Como Adicionar Atrasos no Seu Código (Exemplo)
- Python list.count(): Guia Especializado com Exemplos Práticos
- Python List index(): Como Encontrar Posições de Elementos com Exemplos Práticos