dataclasses, enum & contextlib
dataclasses reduzem o código repetitivo para objetos de dados. enum fornece constantes nomeadas com segurança de tipo. contextlib simplifica gerenciadores de contexto (contextmanager, suppress, ExitStack).
Receita
from dataclasses import dataclass
from enum import StrEnum
from contextlib import contextmanager
class Status(StrEnum):
PENDING = "pending"
DONE = "done"
@dataclass(frozen=True)
class Job:
id: int
status: Status = Status.PENDINGQuando usar:
- DTOs e registros de configuração -> dataclass
- Constantes de modo/estado -> StrEnum
- Escopos rápidos de recursos -> @contextmanager
- Arquivo opcional ausente -> suppress(FileNotFoundError)
- Muitos gerenciadores aninhados -> ExitStack
Exemplo de Trabalho
from contextlib import contextmanager, suppress
from dataclasses import dataclass, field
from enum import StrEnum
class Role(StrEnum):
ADMIN = "admin"
USER = "user"
@dataclass
class Account:
email: str
role: Role = Role.USER
tags: list[str] = field(default_factory=list)
@contextmanager
def temp_role(account: Account, role: Role):
old = account.role
account.role = role
try:
yield account
finally:
account.role = old
ada = Account("ada@example.com")
with temp_role(ada, Role.ADMIN):
print("elevated", ada.role)
print("restored", ada.role)
with suppress(FileNotFoundError):
open("missing.cfg").read()O que isso demonstra:
frozen=Truepara objetos de valor imutáveisfield(default_factory=list)evita o problema de padrão mutável- StrEnum serializa de forma limpa para strings JSON
- contextmanager para estado temporário reversível
Mergulho Profundo
Opções de dataclass
slots=True(3.10+) economia de memóriakw_only=True(3.10+) construção explícita- Validação
__post_init__
Sabores de enum
StrEnumpara APIs JSONIntEnumpara códigos numéricos- Decorador
@uniqueevita duplicatas de alias
Armadilhas
- Dataclass mutável como chave de dicionário - não pode ser hasheada a menos que seja congelada. Correção: frozen=True ou não use instância como chave.
- Comparação de Enum com string bruta - StrEnum compara igual a str no Python 3.11+, mas seja explícito em APIs. Correção: use type hints Role em vez de str.
- contextmanager sem try/finally - a limpeza é ignorada em caso de erro. Correção: envolva yield em try/finally.
- ExitStack esquecido - erros de fechamento manual. Correção: sempre use
with ExitStack(). - dataclass vs Pydantic - dataclass não tem validação. Correção: Pydantic na fronteira HTTP.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Pydantic BaseModel | Validação/coerção | DTO de loop interno rápido |
| TypedDict | Dicionários em formato JSON | Precisa de métodos |
| attrs | Ecossistema attrs | Apenas biblioteca padrão |
FAQs
dataclass vs namedtuple?
dataclass oferece padrões flexíveis e controle de mutabilidade.
enums auto()?
Enum.auto() atribui valores automaticamente para não-StrEnum.
contextlib.closing?
Envolve objetos que podem ser fechados (close()) mas não são gerenciadores de contexto.
asynccontextmanager?
Contraparte assíncrona em contextlib para blocos async with.
field(repr=False)?
Oculta campos sensíveis da saída de repr.
memória de slots?
Mensurável em contagens de instâncias enormes - faça profiling antes de usar slots por padrão em todos os lugares.
serializar enum para JSON?
O .value de StrEnum é str - json.dumps lida com isso em valores de dicionário.
match em enum?
Correspondência estrutural de padrões funciona com membros de enum no Python 3.10+.
testar contexto temporário?
Afirme o estado antes/depois que o bloco with for levantado.
Django choices?
TextChoices/IntegerChoices espelham o padrão enum no Django 5.2.
Relacionado
- Gerenciadores de Contexto como um Padrão - profundidade do padrão
- json & Serialização - StrEnum em JSON
- Recapitulação de collections - Counter com enums
- Melhores Práticas da Biblioteca Padrão - regras ergonômicas
Versões da Pilha: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 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+.