dataclasses
dataclasses (stdlib desde 3.7) gera boilerplate de métodos comuns para classes que primariamente armazenam dados. Elas são a escolha padrão para registros internos antes de se recorrer a modelos ORM completos.
Receita
from dataclasses import dataclass, field
@dataclass
class User:
id: int
name: str
tags: list[str] = field(default_factory=list)Quando usar:
- Eventos de domínio e DTOs dentro de camadas de aplicação
- Objetos de configuração/valor imutáveis (
frozen=True) - Estruturas aninhadas com
__repr__legível para depuração - Substituição de tuplas onde nomes de campo ajudam na legibilidade
Exemplo de Trabalho
from dataclasses import dataclass, field
@dataclass(frozen=True)
class Money:
amount: int
currency: str
def __post_init__(self) -> None:
if self.amount < 0:
raise ValueError("amount must be non-negative")
@dataclass
class Order:
id: int
lines: list[Money] = field(default_factory=list)
def total(self) -> Money:
if not self.lines:
return Money(0, "USD")
currency = self.lines[0].currency
amount = sum(line.amount for line in self.lines)
return Money(amount, currency)
if __name__ == "__main__":
order = Order(1, [Money(100, "USD"), Money(50, "USD")])
print(order)
print(order.total())O que isto demonstra:
frozen=Trueimpede a reatribuição de atributos após a criação__post_init__valida invariantes após__init__default_factory=listcria uma nova lista para cada instância- Métodos coexistem com os métodos gerados pelo dataclass
Mergulho Profundo
Como Funciona
- Decorador transforma a classe - Adiciona métodos com base nos campos e flags no momento da criação da classe.
- Ordem dos campos - Campos sem padrões devem preceder campos com padrões.
- KW_ONLY -
field(kw_only=True)força a passagem por palavra-chave para campos posteriores (3.10+). - slots -
@dataclass(slots=True)combina dataclass com__slots__(3.10+). - replace -
dataclasses.replace(obj, amount=200)atualizações funcionais em instâncias frozen.
Flags Úteis
| Flag | Efeito |
|---|---|
frozen=True | Imutável + hashable (se os campos forem hashable) |
order=True | Gera comparações de ordenação |
slots=True | Instâncias eficientes em memória |
kw_only=True | Todos os campos somente por palavra-chave (3.10+) |
Notas Python
from dataclasses import asdict, astuple
payload = asdict(order) # dict raso - dataclasses aninhados recursivamente
coords = astuple(point)Armadilhas
- Lista padrão mutável -
tags: list = []ainda está quebrado semfield. Correção:field(default_factory=list). - Ordem de campos de herança - Padrões de subclasses são complicados entre MRO. Correção: Mantenha hierarquias rasas ou use composição.
asdictcom mutáveis profundos - Copia a estrutura, mas mutáveis aninhados ainda são aliases se não forem dataclasses. Correção: Conheça as necessidades rasas vs. profundas.frozencom campos mutáveis -frozenimpede a reatribuição delines, mas a lista interna ainda é mutável. Correção: Campos de tupla ou tipos imutáveis.- Comparando com dict - Instância de Dataclass != dict, mesmo que os campos correspondam. Correção: Converta explicitamente para APIs JSON.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
NamedTuple | Tupla imutável semelhante | Precisa de mutabilidade |
TypedDict | Forma de dict JSON | Precisa de métodos/validação |
Pydantic BaseModel | Validação HTTP | Domínio interno sem I/O |
| classe simples | Ciclo de vida complexo | Boilerplate de registro simples |
FAQs
dataclass vs NamedTuple?
dataclass oferece flexibilidade de mutabilidade e métodos. NamedTuple é uma subclasse de tupla imutável mais leve.
Como validar campos?
__post_init__ ou uma camada externa Pydantic nas fronteiras. dataclasses não valida tipos automaticamente em tempo de execução.
Posso personalizar __init__?
Sim, mas geralmente desnecessário - use __post_init__ em vez disso para manter o init gerado.
frozen e hashable?
Dataclasses frozen são hashable quando todos os campos são hashable - ótimo para chaves de dicionário.
field(default=...) vs default_factory?
default para padrões imutáveis (int, str, None). default_factory para criar um novo objeto mutável a cada vez.
slots=True vale a pena?
Milhões de instâncias - economiza memória. Contagens pequenas - evite a complexidade.
herança com dataclasses?
Suportado - preste atenção à ordem dos campos e aos padrões entre pai/filho.
asdict para JSON?
Útil para serialização simples - observe que tipos customizados como datetime/decimal precisam de um codificador customizado.
kw_only em um único campo?
Força o uso de palavra-chave para esse campo ao criar uma instância - APIs mais claras com muitos parâmetros.
dataclass vs attrs?
Mantenha-se no stdlib, a menos que os recursos do attrs (validadores, conversores) já sejam padrão em sua organização.
Relacionados
- Dunder / Métodos Mágicos - métodos gerados
- Propriedades e Descritores - campos computados
- TypedDict & NamedTuple - alternativas de tipagem
- Imutabilidade e Hashability - objetos frozen
Versões do Stack: Esta página foi escrita para Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.