Resumo : neste tutorial, você aprenderá sobre o decorador de classe de dados Python e como usá-lo de maneira eficaz.
Introdução à classe de dados Python
Python introduziu a classe de dados na versão 3.7 ( PEP 557 ). A classe de dados permite definir classes com menos código e mais funcionalidades prontas para uso.
O seguinte define uma Person
classe regular com dois atributos de instância name
e age
:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
Linguagem de código: Python ( python )
Esta Person
classe possui o __init__
método que inicializa os atributos name
e age
.
Se você deseja ter uma representação em string do Person
objeto, você precisa implementar o método __str__
or __repr__
. Além disso, se quiser comparar duas instâncias da Person
classe por um atributo, você precisará implementar o __eq__
método.
No entanto, se você usar a classe de dados, terá todos esses recursos (e ainda mais) sem implementar esses métodos dunder.
Para tornar a Person
classe uma classe de dados, siga estas etapas:
Primeiro, importe o dataclass
decorador do dataclasses
módulo:
from dataclasses import dataclass
Linguagem de código: Python ( python )
Segundo, decore a Person
classe com o dataclass
decorador e declare os atributos:
@dataclass
class Person:
name: str
age: int
Linguagem de código: Python ( python )
Neste exemplo, a Person
classe possui dois atributos name
com o tipo str
e age
com o tipo int
. Ao fazer isso, o decorador @dataclass cria implicitamente o __init__
método assim:
def __init__(name: str, age: int)
Linguagem de código: Python ( python )
Observe que a ordem dos atributos declarados na classe determinará a ordem dos parâmetros no __init__
método.
E você pode criar o Person
objeto ‘:
p1 = Person('John', 25)
Linguagem de código: Python ( python )
Ao imprimir o Person
objeto ‘, você obterá um formato legível:
print(p1)
Linguagem de código: Python ( python )
Saída:
Person(name='John', age=25)
Linguagem de código: Python ( python )
Além disso, se você comparar dois Person
objetos com o mesmo valor de atributo, ele retornará True
. Por exemplo:
p1 = Person('John', 25)
p2 = Person('John', 25)
print(p1 == p2)
Linguagem de código: Python ( python )
Saída:
True
Linguagem de código: Python ( python )
A seguir são discutidas outras funções que uma classe de dados fornece.
Valores padrão
Ao usar uma classe regular, você pode definir valores padrão para atributos. Por exemplo, a Person
classe a seguir possui o iq
parâmetro com o valor padrão 100
.
class Person:
def __init__(self, name, age, iq=100):
self.name = name
self.age = age
self.iq = iq
Linguagem de código: Python ( python )
Para definir um valor padrão para um atributo na classe de dados, atribua-o ao atributo assim:
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
iq: int = 100
print(Person('John Doe', 25))
Linguagem de código: Python ( python )
Assim como as regras de parâmetros, os atributos com valores padrão devem aparecer depois daqueles sem valores padrão. Portanto, o código a seguir não funcionará:
from dataclasses import dataclass
@dataclass
class Person:
iq: int = 100
name: str
age: int
Linguagem de código: Python ( python )
Converter em uma tupla ou dicionário
O dataclasses
módulo possui as funções astuple()
e asdict()
que convertem uma instância da classe de dados em uma tupla e um dicionário . Por exemplo:
from dataclasses import dataclass, astuple, asdict
@dataclass
class Person:
name: str
age: int
iq: int = 100
p = Person('John Doe', 25)
print(astuple(p))
print(asdict(p))
Linguagem de código: Python ( python )
Saída:
('John Doe', 25, 100)
{'name': 'John Doe', 'age': 25, 'iq': 100}
Linguagem de código: Python ( python )
Crie objetos imutáveis
Para criar objetos somente leitura a partir de uma classe de dados, você pode definir o argumento congelado do decorador da classe de dados como True
. Por exemplo:
from dataclasses import dataclass, astuple, asdict
@dataclass(frozen=True)
class Person:
name: str
age: int
iq: int = 100
Linguagem de código: Python ( python )
Se você tentar alterar os atributos do objeto após ele ser criado, você receberá um erro. Por exemplo:
p = Person('Jane Doe', 25)
p.iq = 120
Linguagem de código: Python ( python )
Erro:
dataclasses.FrozenInstanceError: cannot assign to field 'iq'
Linguagem de código: Python ( python )
Personalize comportamentos de atributos
Se não quiser inicializar um atributo no método __init__, você pode usar a field()
função do dataclasses
módulo.
O exemplo a seguir define o can_vote
atributo que é inicializado usando o __init__
método:
from dataclasses import dataclass, field
class Person:
name: str
age: int
iq: int = 100
can_vote: bool = field(init=False)
Linguagem de código: Python ( python )
A função possui vários parâmetros interessantes , field()
como repr
,,, e .hash
compare
metadata
Se quiser inicializar um atributo que depende do valor de outro atributo, você pode usar o __post_init__
método. Como o próprio nome indica, Python chama o __post_init__
método após o __init__
método.
A seguir, use o __post_init__
método para inicializar o can_vote
atributo com base no age
atributo:
from dataclasses import dataclass, field
@dataclass
class Person:
name: str
age: int
iq: int = 100
can_vote: bool = field(init=False)
def __post_init__(self):
print('called __post_init__ method')
self.can_vote = 18 <= self.age <= 70
p = Person('Jane Doe', 25)
print(p)
Linguagem de código: Python ( python )
Saída:
called the __post_init__ method
Person(name='Jane Doe', age=25, iq=100, can_vote=True)
Linguagem de código: Python ( python )
Classificar objetos
Por padrão, uma classe de dados implementa o __eq__
método.
Para permitir diferentes tipos de comparações como __lt__
, __lte__
, __gt__
, __gte__
, você pode definir o argumento order do @dataclass
decorador como True:
@dataclass(order=True)
Linguagem de código: CSS ( css )
Ao fazer isso, a classe de dados classificará os objetos por cada campo até encontrar um valor diferente.
Na prática, muitas vezes você deseja comparar objetos por um atributo específico, não por todos os atributos. Para fazer isso, você precisa definir um campo chamado sort_index
e definir seu valor para o atributo que deseja classificar.
Por exemplo, suponha que você tenha uma lista de Person
objetos e queira classificá-los por idade:
members = [
Person('John', 25),
Person('Bob', 35),
Person('Alice', 30)
]
Linguagem de código: Python ( python )
Para fazer isso, você precisa:
- Primeiro, passe o
order=True
parâmetro para o@dataclass
decorador. - Segundo, defina o
sort_index
atributo e defina seuinit
parâmetro comoFalse
. - Terceiro, defina the
sort_index
como oage
atributo no__post_init__
método para classificar oPerson
objeto por idade.
O seguinte mostra o código para classificar Person
os objetos por idade:
from dataclasses import dataclass, field
@dataclass(order=True)
class Person:
sort_index: int = field(init=False, repr=False)
name: str
age: int
iq: int = 100
can_vote: bool = field(init=False)
def __post_init__(self):
self.can_vote = 18 <= self.age <= 70
# sort by age
self.sort_index = self.age
members = [
Person(name='John', age=25),
Person(name='Bob', age=35),
Person(name='Alice', age=30)
]
sorted_members = sorted(members)
for member in sorted_members:
print(f'{member.name}(age={member.age})')
Linguagem de código: Python ( python )
Saída:
John(age=25)
Alice(age=30)
Bob(age=35)
Linguagem de código: Python ( python )
Resumo
- Use o
@dataclass
decorador dodataclasses
módulo para transformar uma classe em uma classe de dados. O objeto dataclass implementa__eq__
e__str__
por padrão. - Use as funções
astuple()
easdict()
para converter um objeto de uma classe de dados em uma tupla e um dicionário. - Use
frozen=True
para definir uma classe cujos objetos são imutáveis. - Use
__post_init__
o método para inicializar atributos que dependem de outros atributos. - Use
sort_index
para especificar os atributos de classificação dos objetos de classe de dados.