types.new_class no Python: classes dinâmicas

Publicado em: 30/08/2026
Tempo de leitura: 4 minutos
High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.

types.new_class() cria classes dinamicamente usando as mesmas regras centrais de uma declaração class. A função escolhe a metaclass apropriada, prepara o namespace e executa um callback que adiciona atributos, métodos e metadados antes de construir o tipo final.

Ela é útil em frameworks, ORMs, geradores de modelos, sistemas de plugins e ferramentas que precisam produzir classes a partir de schemas. Para casos simples, a função embutida type() pode bastar; new_class é valiosa quando metaclasses, __prepare__ e bases dinâmicas importam.

Assinatura

types.new_class(name, bases=(), kwds=None, exec_body=None)

name define o nome, bases contém as classes base, kwds representa opções do cabeçalho da classe e exec_body recebe o namespace preparado.

Primeiro exemplo

from types import new_class

def preencher(namespace):
    namespace["categoria"] = "dinâmica"
    namespace["descrever"] = lambda self: self.categoria

Produto = new_class("Produto", (), {}, preencher)
print(Produto().descrever())

O callback modifica o namespace antes da criação. Evite lambdas quando métodos precisam de documentação ou lógica significativa.

Equivalência conceitual

class Produto:
    categoria = "dinâmica"

    def descrever(self):
        return self.categoria

A declaração normal é preferível quando a estrutura é conhecida ao escrever o código. Use geração dinâmica quando os campos ou bases realmente são determinados em runtime.

Usando uma classe base

class Modelo:
    def salvar(self):
        print("salvando", type(self).__name__)

def corpo(ns):
    ns["tabela"] = "clientes"

Cliente = new_class("Cliente", (Modelo,), exec_body=corpo)

A classe criada participa normalmente de herança, MRO, descriptors e super().

Metaclass explícita

class Meta(type):
    def __new__(mcls, nome, bases, namespace):
        namespace["registrada"] = True
        return super().__new__(mcls, nome, bases, namespace)

Gerada = new_class(
    "Gerada",
    (),
    {"metaclass": Meta},
    lambda ns: ns.update(valor=10),
)

O dicionário kwds representa argumentos do cabeçalho de classe. A opção metaclass é usada para selecionar a metaclass e não permanece necessariamente no namespace.

__prepare__ e namespaces especiais

Metaclasses podem implementar __prepare__ para devolver um mapping personalizado. new_class respeita esse protocolo, ao contrário de abordagens manuais que montam um dicionário e chamam type diretamente.

types.prepare_class

Quando você precisa controlar cada etapa, types.prepare_class() calcula a metaclass e devolve o namespace preparado. new_class combina essas etapas em uma interface mais conveniente.

Bases dinâmicas e __mro_entries__

Objetos usados como bases podem fornecer __mro_entries__ para serem substituídos por classes reais. O módulo types também oferece resolve_bases. Esse mecanismo aparece em genéricos e frameworks avançados.

Adicionando métodos com closure

def criar_modelo(nome, campos):
    def corpo(ns):
        ns["__annotations__"] = dict(campos)

        def __repr__(self):
            valores = ", ".join(
                f"{campo}={getattr(self, campo, None)!r}"
                for campo in campos
            )
            return f"{nome}({valores})"

        ns["__repr__"] = __repr__

    return new_class(nome, (), exec_body=corpo)

Tenha cuidado com closures em loops. Capture valores deliberadamente para evitar que todos os métodos usem a última iteração.

Definindo __module__ e __qualname__

Classes geradas para uso público devem ter metadados coerentes. Defina __module__ quando necessário para documentação, pickling e mensagens de erro.

def corpo(ns):
    ns["__module__"] = __name__
    ns["__doc__"] = "Modelo criado dinamicamente."

Pickle e importabilidade

Para serializar instâncias com pickle, a classe geralmente precisa estar acessível por um nome importável no módulo indicado. Criar a classe dentro de uma função sem registrá-la no namespace do módulo pode impedir a reconstrução.

Decorators depois da criação

Você pode aplicar dataclasses.dataclass, registradores ou outros decorators à classe retornada. Entretanto, frameworks que dependem do momento de criação podem exigir atributos no exec_body.

Segurança

Não transforme schemas não confiáveis diretamente em nomes de atributos, bases, metaclasses ou código executável. Valide identificadores, use listas permitidas e nunca execute texto externo com exec apenas para gerar uma classe.

new_class versus type

type(nome, bases, namespace) é simples e adequado quando o namespace já está pronto. new_class é melhor quando você quer reproduzir o processo de uma declaração de classe, incluindo seleção de metaclass e namespace preparado.

Erros comuns

  • Gerar classes quando uma dataclass ou objeto simples bastaria.
  • Esquecer __module__ e prejudicar pickle ou documentação.
  • Capturar variáveis de loop incorretamente em closures.
  • Confiar em metaclasses ou bases fornecidas externamente.
  • Não testar herança, MRO e introspecção.

Boas práticas

Mantenha uma factory central, valide schemas, crie nomes determinísticos, preserve metadados e teste a classe como qualquer API pública. Leia também os guias internos sobre módulo types, orientação a objetos e dataclasses.

Conclusão

types.new_class oferece uma forma estruturada de gerar classes em runtime respeitando metaclasses, namespaces preparados e herança. Ele é indicado para infraestrutura e frameworks em que a definição realmente depende de dados dinâmicos.

Fontes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Detailed view of computer code highlighting syntax in colors on a screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    partialmethod: crie métodos especializados no Python

    Aprenda partialmethod no Python para criar métodos especializados com binding correto, menos wrappers e APIs de domínio mais claras.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    A detailed image of a reticulated python showcasing its patterned scales and intricate skin texture.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    inspect.getmembers_static: liste atributos sem executar

    Use inspect.getmembers_static no Python para listar atributos sem executar properties, descriptors ou resolução dinâmica indesejada.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    Close-up of a python snake curled up, showcasing its detailed scales.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    DynamicClassAttribute: descriptors e acesso dinâmico

    Entenda DynamicClassAttribute no Python, descriptors, acesso por classe e instância, metaclasses, Enum e introspecção segura.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    UserList no Python: listas customizadas

    Aprenda UserList no Python para criar listas customizadas com validação, normalização, regras de mutação e APIs previsíveis.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    Close-up of a person underlining text in a dictionary on a desk with a laptop.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    UserDict no Python: dicionários customizados

    Aprenda UserDict no Python para criar dicionários customizados com validação, normalização, composição e APIs previsíveis.

    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

    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