UserDict no Python: dicionários customizados

Publicado em: 30/08/2026
Tempo de leitura: 3 minutos
Close-up of a person underlining text in a dictionary on a desk with a laptop.

collections.UserDict é uma classe auxiliar para criar dicionários personalizados por composição. Em vez de depender diretamente da implementação interna de dict, ela armazena os dados em um atributo chamado data e encaminha as operações de mapeamento para esse objeto.

Essa estrutura facilita validação de chaves, normalização de valores, logging, controle de acesso e criação de APIs previsíveis. Também reduz algumas surpresas que podem ocorrer ao sobrescrever métodos de uma subclasse direta de dict.

Primeiro exemplo

from collections import UserDict

class ChavesTexto(UserDict):
    def __setitem__(self, chave, valor):
        if not isinstance(chave, str):
            raise TypeError("a chave deve ser texto")
        super().__setitem__(chave, valor)

dados = ChavesTexto()
dados["nome"] = "Ada"

A validação fica centralizada em __setitem__. Operações como update tendem a respeitar o comportamento personalizado porque a classe foi projetada para extensibilidade.

O atributo data

config = ChavesTexto({"modo": "produção"})
print(config.data)

data contém o dicionário real. Use-o com cuidado: modificar esse atributo diretamente pode ignorar validações implementadas em métodos públicos.

Normalizando chaves

class DicionarioCasefold(UserDict):
    def __setitem__(self, chave, valor):
        super().__setitem__(str(chave).casefold(), valor)

    def __getitem__(self, chave):
        return super().__getitem__(str(chave).casefold())

    def __contains__(self, chave):
        return super().__contains__(str(chave).casefold())

Quando uma chave é normalizada, aplique a mesma regra em leitura, escrita, remoção e teste de presença.

Valores validados

class Pontuacoes(UserDict):
    def __setitem__(self, jogador, pontos):
        pontos = int(pontos)
        if pontos < 0:
            raise ValueError("pontuação negativa")
        super().__setitem__(jogador, pontos)

Evite coerções silenciosas que possam esconder erros. Documente claramente quais conversões são permitidas.

Valor padrão com __missing__

class Contadores(UserDict):
    def __missing__(self, chave):
        return 0

__missing__ é acionado por __getitem__, não necessariamente por get ou testes de presença. Se você precisa inserir automaticamente valores, defaultdict pode ser mais apropriado.

UserDict versus dict

Herdar diretamente de dict pode oferecer desempenho um pouco melhor e integração natural com APIs que exigem o tipo concreto. UserDict oferece uma superfície mais simples para personalização, porque muitas operações passam pelos métodos sobrescritos.

UserDict versus MutableMapping

Implementar collections.abc.MutableMapping é útil quando os dados não são guardados em um dicionário comum, por exemplo em banco de dados, cache remoto ou estrutura compacta. Nesse caso, você implementa os métodos fundamentais. UserDict é melhor quando um dicionário interno resolve o armazenamento.

Cópias

Teste copy, deepcopy e o construtor da classe. Atributos adicionais podem exigir uma implementação própria para serem preservados.

class Config(UserDict):
    def __init__(self, *args, origem=None, **kwargs):
        self.origem = origem
        super().__init__(*args, **kwargs)

Serialização

Muitas bibliotecas JSON aceitam apenas dict concreto. Converta explicitamente quando necessário:

import json

texto = json.dumps(dict(config), ensure_ascii=False)

Imutabilidade parcial

Você pode bloquear alterações depois de uma fase de configuração, sobrescrevendo métodos mutáveis. Porém, para uma visão realmente somente leitura, considere types.MappingProxyType, apresentado no guia interno sobre MappingProxyType.

Erros comuns

  • Modificar data diretamente e ignorar validações.
  • Normalizar somente em __setitem__.
  • Esquecer métodos de remoção e atualização.
  • Assumir que toda biblioteca aceita qualquer Mapping.
  • Adicionar efeitos colaterais surpreendentes a operações simples.

Boas práticas

Mantenha invariantes pequenas e claras, use super(), escreva testes para todas as operações mutáveis e exponha métodos de domínio quando uma alteração exigir regras complexas. Veja também os artigos internos sobre dicionários e collections.

Conclusão

UserDict é uma base prática para mappings personalizados que ainda usam um dicionário comum como armazenamento. Ele favorece composição e torna validação, normalização e instrumentação mais previsíveis.

Fontes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    itertools.accumulate: somas e estados cumulativos

    Aprenda itertools.accumulate no Python para somas, saldos, máximos progressivos e estados cumulativos em pipelines eficientes.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    A person reads 'Python for Unix and Linux System Administration' indoors.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    itertools.groupby: agrupe dados ordenados corretamente

    Aprenda itertools.groupby no Python para agrupar dados ordenados, agregar streams e evitar erros com subiteradores compartilhados.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.chdir: riscos ao trocar diretórios

    Aprenda contextlib.chdir no Python, seus riscos com estado global e concorrência e quando preferir pathlib ou subprocess cwd.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    nullcontext no Python: contextos opcionais

    Use nullcontext no Python para unificar contextos opcionais, recursos já abertos, locks e transações sem duplicar código.

    Ler mais

    Tempo de leitura: 5 minutos
    30/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.aclosing: feche geradores async

    Aprenda contextlib.aclosing no Python para fechar geradores assíncronos em break, return, exceções e cancelamentos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    30/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    weakref.finalize: limpeza automática sem reter objetos

    Aprenda weakref.finalize no Python para limpar recursos sem manter objetos vivos, usando close, detach, alive e callbacks seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    30/08/2026