Classe de dados Python

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 Personclasse regular com dois atributos de instância namee age:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
Linguagem de código:  Python  ( python )

Esta Personclasse possui o __init__método que inicializa os atributos namee age.

Se você deseja ter uma representação em string do Personobjeto, você precisa implementar o método __str__or __repr__. Além disso, se quiser comparar duas instâncias da Personclasse 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 Personclasse uma classe de dados, siga estas etapas:

Primeiro, importe o dataclassdecorador do dataclassesmódulo:

from dataclasses import dataclassLinguagem de código:  Python  ( python )

Segundo, decore a Personclasse com o dataclassdecorador e declare os atributos:

@dataclass
class Person:
    name: str
    age: intLinguagem de código:  Python  ( python )

Neste exemplo, a Personclasse possui dois atributos namecom o tipo stre agecom 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 Personobjeto ‘:

p1 = Person('John', 25)Linguagem de código:  Python  ( python )

Ao imprimir o Personobjeto ‘, 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 Personobjetos 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:

TrueLinguagem 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 Personclasse a seguir possui o iqparâmetro com o valor padrão 100.

class Person:
    def __init__(self, name, age, iq=100):
        self.name = name
        self.age = age
        self.iq = iqLinguagem 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: intLinguagem de código:  Python  ( python )

Converter em uma tupla ou dicionário

O dataclassesmó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 = 100Linguagem 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 = 120Linguagem 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 dataclassesmódulo.

O exemplo a seguir define o can_voteatributo 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 .hashcomparemetadata

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_voteatributo com base no ageatributo:

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 @dataclassdecorador 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_indexe definir seu valor para o atributo que deseja classificar.

Por exemplo, suponha que você tenha uma lista de Personobjetos 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=Trueparâmetro para o @dataclassdecorador.
  • Segundo, defina o sort_indexatributo e defina seu initparâmetro como False.
  • Terceiro, defina the sort_indexcomo o ageatributo no __post_init__método para classificar o Personobjeto por idade.

O seguinte mostra o código para classificar Personos 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 @dataclassdecorador do dataclassesmó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()e asdict()para converter um objeto de uma classe de dados em uma tupla e um dicionário.
  • Use frozen=Truepara 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_indexpara especificar os atributos de classificação dos objetos de classe de dados.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *