Módulo 3 - Dataclasses e estruturas de dados

field e default_factory: valores mutáveis

10 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Entender o bug de valor mutável compartilhado entre instâncias.
  • Usar field com default_factory para criar valores novos por instância.
  • Reconhecer que o Python barra listas como default direto na dataclass.
  • Conhecer outros usos do field na configuração de campos.

Por que uma lista não pode ser padrão direto

Há uma armadilha clássica em Python: usar um valor mutável, como uma lista, de valor padrão. Se o padrão fosse uma única lista criada uma vez, todas as instâncias sem valor explícito acabariam compartilhando a mesma lista. Alterar a lista de um objeto mudaria a de todos os outros, um bug difícil de rastrear. A dataclass conhece esse perigo e simplesmente proíbe: se você tentar usar uma lista como default direto, o Python levanta um erro na definição da classe.

from dataclasses import dataclass

# Isto levanta erro ao definir a classe:
# @dataclass
# class Carrinho:
#     itens: list[str] = []   # ValueError: mutable default

# O Python impede porque a lista seria compartilhada entre instancias.
# A solucao correta esta na proxima secao, com default_factory.

Uma lista como default direto é barrada: evitaria o bug do estado compartilhado.

default_factory cria um valor novo por instância

A solução é o field com default_factory. Em vez de dar um valor pronto, você dá uma função que produz o valor. A dataclass chama essa função a cada nova instância, gerando um objeto novo toda vez. Para uma lista vazia, a factory é a própria função list; para um dicionário vazio, é dict. Assim cada objeto ganha a sua lista, e alterar uma não afeta as outras. É o jeito correto e seguro de ter coleções como campo padrão.

from dataclasses import dataclass, field

@dataclass
class Carrinho:
    dono: str
    itens: list[str] = field(default_factory=list)

c1 = Carrinho("Ana")
c2 = Carrinho("Beto")
c1.itens.append("cafe")

print(c1.itens)  # ['cafe']
print(c2.itens)  # []  <- lista independente, sem contagio

field(default_factory=list) dá a cada carrinho a sua própria lista vazia.

No exemplo, c1 e c2 têm listas independentes. Adicionar cafe ao carrinho de Ana não toca no de Beto, exatamente como se espera. A factory list é chamada duas vezes, uma para cada instância, produzindo duas listas distintas. Você pode passar qualquer função sem argumentos como factory, inclusive uma sua, por exemplo uma que devolva um dicionário já com valores iniciais.

Outros usos do field

Além do default_factory, o field configura outros detalhes de um campo. Você pode marcar um campo para não entrar na comparação de igualdade, útil quando ele guarda algo como um cache que não define a identidade do objeto. Pode marcar um campo para ficar fora do __repr__, escondendo dados sensíveis da representação. E pode declarar um campo que não vai para o __init__, sendo preenchido no __post_init__, tema da próxima aula. O field é o ponto de ajuste fino de cada campo.

Parâmetro de fieldPara que serve
default_factoryCria um valor novo por instância (listas, dicionários)
defaultValor padrão simples, alternativa ao sinal de igual
compareSe False, o campo fica fora do __eq__
reprSe False, o campo fica fora do __repr__

O field ajusta cada campo além do valor padrão.

Na prática, o default_factory é de longe o uso mais comum do field, porque coleções como campo aparecem o tempo todo. Guarde a regra: valor imutável, como número ou texto, pode ser default direto; valor mutável, como lista ou dict, pede default_factory. Com isso você modela estruturas ricas sem cair na armadilha do estado compartilhado, e a próxima aula fecha o assunto de robustez com imutabilidade e validação.

Teste rápido

Por que se usa field(default_factory=list) em vez de igual a uma lista vazia direto?

Perguntas frequentes

Posso usar minha própria função como default_factory?
Sim, desde que ela não receba argumentos. A dataclass a chama sem parâmetros a cada nova instância. Você pode passar uma função que devolve um dicionário já preenchido, uma lista com valores iniciais ou qualquer objeto que faça sentido como padrão daquele campo.
Números e textos também precisam de default_factory?
Não. Valores imutáveis, como int, float, str, bool e tuplas de imutáveis, podem ser default direto com o sinal de igual, sem risco de compartilhamento, porque não dá para alterá-los no lugar. A factory é para valores mutáveis, como listas, dicionários e conjuntos.
O que acontece se eu insistir numa lista como default direto?
A dataclass levanta um ValueError já na definição da classe, com uma mensagem indicando o problema do mutable default. É uma proteção deliberada: em vez de deixar o bug de estado compartilhado passar, o Python interrompe e sugere o default_factory. Assim o erro aparece cedo.
O compare=False do field muda o __repr__ também?
Não, são controles separados. O compare=False tira o campo apenas da comparação de igualdade, o __eq__. Para tirá-lo da representação, você usa repr=False. Você pode combinar os dois num mesmo campo se quiser escondê-lo tanto da comparação quanto da exibição.
default_factory funciona com dicionários e conjuntos?
Funciona com qualquer valor mutável. Para um dicionário vazio, use default_factory=dict; para um conjunto vazio, default_factory=set. A regra é a mesma da lista: como esses tipos são mutáveis, cada instância precisa do seu próprio, e a factory garante isso.
Preciso importar field separadamente?
Sim, do mesmo módulo: from dataclasses import dataclass, field. O dataclass é o decorador; o field é a função que configura um campo específico. Ambos vêm na biblioteca padrão, então não há nada para instalar, e os dois costumam ser importados na mesma linha.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.