Módulo Dataclasses em Python
O módulo dataclasses fornece o decorador dataclass, que permite criar data classes, as quais reduzem significativamente o código repetitivo (boilerplate) das classes. Geralmente, tais classes são destinadas a armazenar algum estado ou dados, quando não é necessário algum comportamento na forma de funções.
Vamos considerar um exemplo simples:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
tom = Person("Tom", 38)
print(f"Name: {tom.name} Age: {tom.age}") # Name: Tom Age: 38Aqui, definimos a classe Person, na qual, na função construtora __init__, são estabelecidos dois atributos: name e age. Em seguida, criamos um objeto dessa classe e exibimos os valores de seus atributos no console.
Agora, vamos modificar este programa, transformando a classe Person em uma data class:
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
tom = Person("Tom", 38)
print(f"Name: {tom.name} Age: {tom.age}") # Name: Tom Age: 38Para criar uma data class, importamos do módulo dataclasses o decorador dataclass e o aplicamos à classe Person. Nesse caso, não precisamos mais especificar o construtor, a função __init__. Simplesmente declaramos os atributos, e o Python irá gerar o construtor, no qual podemos passar os valores para os atributos do objeto.
Assim, reduzimos a definição da classe e a tornamos mais simples. Mas a funcionalidade do decorador dataclass não se limita à criação do método __init__. Na realidade, a data class
@dataclass
class Person:
name: str
age: inté equivalente ao seguinte:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name={self.name!r}, age={self.age!r})"
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.age) == (other.name, other.age)
return NotImplementedNesse caso, vemos que, além da função __init__, também são definidas as funções __repr__() para retornar uma representação em string e __eq__() para comparar dois objetos. Para entender melhor como funciona a sobrecarga de operadores em Python, consulte este artigo. Aplicação dessas funções: Aplicação dessas funções:
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
tom = Person("Tom", 38)
bob = Person("Bob", 42)
tomas = Person("Tom", 38)
print(tom == tomas) # True
print(tom == bob) # False
print(tom) # Person(name='Tom', age=38)Parâmetros do decorador dataclass
Com a ajuda de parâmetros, o decorador dataclass permite gerar código adicional e personalizar a funcionalidade da data class:
def dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False,
unsafe_hash=False, frozen=False, match_args=True,
kw_only=False, slots=False)Vamos considerar os parâmetros básicos:
init: se forTrue, gera a função__init__(). Por padrão, éTrue.repr: se forTrue, gera a função__repr__(), que retorna uma representação em string do objeto. Por padrão, éTrue.eq: se forTrue, gera a função__eq__(), que compara dois objetos. Por padrão, éTrue.order: se forTrue, gera as funções__lt__(operação <),__le__(<=),__gt__(>),__ge__(>=), que são usadas para ordenar objetos. Por padrão, éFalse.unsafe_hash: se forTrue, gera a função__hash__(), que retorna o hash do objeto. Por padrão, éFalse.
Além disso, as funções que são criadas por padrão podem ser sobrescritas.
Aplicação dos parâmetros:
from dataclasses import dataclass
@dataclass(unsafe_hash=True, order=True)
class Person:
name: str
age: int
def __repr__(self):
return f"Person. Name: {self.name} Age: {self.age}"
tom = Person("Tom", 38)
print(hash(tom)) # Exemplo de saída: -421667297069596717
print(tom) # Person. Name: Tom Age: 38Neste caso, ativamos a criação do hash e das funções de ordenação, além de sobrescrever explicitamente a função __repr__ para criar uma representação em string do objeto.
Valores padrão
Se necessário, os atributos podem receber valores padrão caso não sejam passados valores a eles no construtor:
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int = 18
tom = Person("Tom", 38)
print(tom) # Person(name='Tom', age=38)
bob = Person("Bob")
print(bob) # Person(name='Bob', age=18)Adicionando funcionalidade extra
Embora as data classes sejam destinadas principalmente ao armazenamento de dados, também é possível definir métodos adicionais:
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
def say_hello(self):
print(f"{self.name} says hello")
tom = Person("Tom", 38)
tom.say_hello() # Tom says helloDocumentação oficial: