DynamicClassAttribute: descriptors e acesso dinâmico

Publicado em: 30/08/2026
Tempo de leitura: 3 minutos
Close-up of a python snake curled up, showcasing its detailed scales.

types.DynamicClassAttribute é um descriptor especializado que se comporta como uma propriedade quando acessado por uma instância, mas permite que o acesso pela classe seja encaminhado ao __getattr__ da própria classe. Esse comportamento é incomum e foi criado para APIs em que um mesmo nome precisa ter significado diferente no nível da instância e no nível da classe.

O exemplo mais conhecido está relacionado a Enum. Antes de usar o recurso diretamente, é importante entender descriptors, propriedades e metaclasses.

Comportamento básico

from types import DynamicClassAttribute

class Item:
    def __init__(self, valor):
        self._valor = valor

    @DynamicClassAttribute
    def valor(self):
        return self._valor

item = Item(10)
print(item.valor)

Na instância, o descriptor funciona de forma semelhante a property.

Acesso pela classe

Quando Item.valor é acessado, o descriptor levanta AttributeError. Isso permite que uma metaclass com __getattr__ forneça uma resposta dinâmica.

class Meta(type):
    def __getattr__(cls, nome):
        if nome == "valor":
            return "valor calculado na classe"
        raise AttributeError(nome)

class Item(metaclass=Meta):
    @DynamicClassAttribute
    def valor(self):
        return 42

print(Item().valor)
print(Item.valor)

A instância retorna 42; a classe usa o fallback da metaclass.

Diferença para property

Uma property comum acessada pela classe normalmente devolve o próprio objeto descriptor. DynamicClassAttribute foi projetado para provocar o caminho de atributo ausente no nível da classe.

Descriptors e __get__

Descriptors controlam acesso por meio de métodos como __get__, __set__ e __delete__. DynamicClassAttribute encapsula esse protocolo e suporta getter, setter e deleter, assim como property.

class Registro:
    def __init__(self):
        self._codigo = "A1"

    @DynamicClassAttribute
    def codigo(self):
        return self._codigo

    @codigo.setter
    def codigo(self, valor):
        self._codigo = str(valor)

Uso com metaclasses

O recurso só mostra seu diferencial quando a classe usa uma metaclass capaz de responder dinamicamente. O método __getattr__ deve ser implementado na metaclass, não como método de instância da classe.

Por que Enum usa uma ideia semelhante

Enums precisam distinguir membros, atributos de instância e resolução de nomes no nível da classe. O mecanismo permite que nomes sejam tratados dinamicamente sem perder propriedades úteis nas instâncias.

Quando usar

  • Frameworks com metaclasses e namespaces dinâmicos.
  • APIs em que o mesmo nome tem semântica distinta na classe e na instância.
  • Implementações inspiradas em Enum.
  • Ferramentas de introspecção ou proxies de tipos.

Quando evitar

Na maioria das aplicações, nomes diferentes ou métodos de classe explícitos são mais claros. O recurso aumenta a complexidade de introspecção, autocompletar, documentação e análise estática. Não o use apenas para economizar um nome.

Introspecção

getattr(Classe, nome) pode executar o fallback dinâmico. Para inspecionar descriptors sem dispará-los, use inspect.getattr_static ou inspect.getmembers_static.

import inspect

descriptor = inspect.getattr_static(Item, "valor")
print(type(descriptor))

Tipagem

Type checkers podem não compreender completamente namespaces produzidos por metaclasses. Considere stubs, overloads ou protocolos e mantenha a API pública simples.

Erros comuns

  • Implementar __getattr__ na classe em vez da metaclass.
  • Esperar que o acesso pela classe devolva o descriptor.
  • Criar recursão dentro de __getattr__.
  • Usar o mecanismo onde uma property normal bastaria.
  • Ignorar ferramentas de introspecção e documentação.

Boas práticas

Restrinja o recurso a infraestrutura, teste acesso por classe e instância, preserve mensagens de AttributeError e documente claramente a semântica dupla. Leia também os guias internos sobre módulo types, Enums e introspecção.

Conclusão

DynamicClassAttribute combina comportamento de propriedade na instância com resolução dinâmica no nível da classe. É poderoso em frameworks baseados em metaclasses, mas deve ser usado com parcimônia devido à complexidade adicionada.

Fontes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código Python em um notebook para criar dataclasses dinâmicas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    make_dataclass decorator: transforme dataclasses

    Aprenda a usar o parâmetro decorator de make_dataclass para validar, registrar e transformar dataclasses dinâmicas no Python.

    Ler mais

    Tempo de leitura: 6 minutos
    23/10/2026
    Estrutura de código e XML para canonicalização com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: normalize XML no Python

    Aprenda ElementTree canonicalize no Python para comparar XML, gerar hashes estáveis e controlar namespaces, espaços e comentários.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Código de programação Python em uma tela
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    T-strings e templatelib: interpolação estruturada

    Aprenda t-strings e string.templatelib no Python para processar interpolações, criar renderizadores seguros e preservar dados estruturados.

    Ler mais

    Tempo de leitura: 6 minutos
    22/10/2026
    Banco SQLite e código Python para exportação seletiva com iterdump
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: crie dumps seletivos no Python

    Aprenda sqlite3.Connection.iterdump com filtro para gerar dumps seletivos, validar dependências e restaurar bancos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    21/10/2026
    Código e arquivos representando compressão de dados no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Zstandard rápido no Python

    Aprenda a usar compression.zstd no Python para comprimir e descomprimir dados com desempenho, streaming e segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    21/10/2026
    Arquivo de configuração e estrutura de código para ConfigParser no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ConfigParser: leia INI sem seção no Python

    Aprenda a ler arquivos INI sem cabeçalho usando ConfigParser, com validação, tipos, compatibilidade e escrita segura.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026