types.new_class en Python: clases dinámicas

Publicado el: 30/08/2026
Tempo de leitura: 3 minutos
A person typing on a laptop with a Python programming book visible, capturing technology and learning.

types.new_class() crea clases dinámicamente siguiendo las reglas principales de una declaración class. Selecciona la metaclase apropiada, prepara el namespace y ejecuta un callback que añade atributos, métodos y metadatos antes de construir el tipo final.

Es útil en frameworks, ORMs, generadores de modelos, sistemas de plugins y APIs basadas en schemas. Para casos simples, type() puede ser suficiente; new_class es valiosa cuando importan metaclases, __prepare__ o bases dinámicas.

Firma

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

name define el nombre, bases contiene las clases base, kwds representa opciones del encabezado y exec_body recibe el namespace preparado.

Ejemplo básico

from types import new_class

def completar(namespace):
    namespace["categoria"] = "dinámica"

    def describir(self):
        return self.categoria

    namespace["describir"] = describir

Producto = new_class("Producto", (), {}, completar)
print(Producto().describir())

El callback modifica el namespace antes de la creación.

Equivalencia conceptual

class Producto:
    categoria = "dinámica"

    def describir(self):
        return self.categoria

Una declaración normal es preferible cuando la estructura se conoce al escribir el programa. La generación dinámica debe reservarse para definiciones determinadas en runtime.

Usar una clase base

class Modelo:
    def guardar(self):
        print("guardando", type(self).__name__)

def cuerpo(ns):
    ns["tabla"] = "clientes"

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

La clase generada participa normalmente en herencia, MRO, descriptors y super().

Metaclase explícita

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

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

El diccionario kwds corresponde a keywords del encabezado de clase. La opción metaclass participa en la creación y no se convierte en un atributo ordinario.

__prepare__ y namespaces especiales

Las metaclases pueden implementar __prepare__ para devolver un mapping especializado. new_class respeta este protocolo, a diferencia de una solución simple que crea un diccionario y llama a type.

types.prepare_class

Para controlar todas las etapas, types.prepare_class() calcula la metaclase y devuelve el namespace preparado. new_class combina esos pasos en una interfaz cómoda.

Bases dinámicas y __mro_entries__

Objetos usados como bases pueden ofrecer __mro_entries__ y ser reemplazados por clases reales. El módulo types también incluye resolve_bases. Este mecanismo aparece en genéricos y frameworks avanzados.

Métodos con closures

def crear_modelo(nombre, campos):
    def cuerpo(ns):
        ns["__annotations__"] = dict(campos)

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

        ns["__repr__"] = __repr__

    return new_class(nombre, (), exec_body=cuerpo)

Ten cuidado con la captura de variables de loops al generar varios métodos.

Definir __module__ y __qualname__

Las clases públicas generadas necesitan metadatos coherentes para documentación, errores y serialización.

def cuerpo(ns):
    ns["__module__"] = __name__
    ns["__doc__"] = "Modelo generado dinámicamente."

Pickle e importabilidad

Pickle normalmente necesita que la clase sea accesible mediante un nombre importable. Una clase creada dentro de una función puede tener que registrarse en el namespace del módulo.

Aplicar decorators

La clase devuelta puede pasarse a dataclasses.dataclass, registradores u otros decorators. Los frameworks que inspeccionan durante la creación pueden requerir atributos dentro de exec_body.

Seguridad

No conviertas schemas no confiables directamente en bases, metaclases, identificadores o código ejecutable. Valida nombres, usa listas permitidas y evita exec cuando una construcción estructurada sea suficiente.

new_class frente a type

type(nombre, bases, namespace) es conciso cuando el namespace ya está disponible. new_class es mejor cuando necesitas reproducir el proceso de definición, incluida la selección de metaclase y el namespace preparado.

Errores comunes

  • Generar una clase cuando una dataclass u objeto simple basta.
  • Olvidar __module__ y perjudicar pickle o documentación.
  • Capturar mal variables de loops.
  • Confiar en bases o metaclases externas.
  • No probar MRO, herencia e introspección.

Buenas prácticas

Centraliza la generación en una factory, valida schemas, usa nombres deterministas, conserva metadatos y prueba las clases como APIs públicas. Consulta las guías internas sobre módulo types, programación orientada a objetos y dataclasses.

Conclusión

types.new_class ofrece una forma estructurada de generar clases en runtime respetando metaclases, namespaces preparados y herencia. Es adecuada para infraestructura basada en definiciones dinámicas.

Fuentes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Carpetas y directorios para contextlib.chdir en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.chdir: restaura directorios automáticamente

    Aprende contextlib.chdir en Python para cambiar directorios temporalmente, restaurar rutas y crear pruebas confiables sin errores de estado global.

    Ler mais

    Tempo de leitura: 6 minutos
    03/09/2026
    Monitoreo de rendimiento y ejecución de código Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sys.monitoring: instrumentación de bajo overhead

    Aprende sys.monitoring en Python para instrumentar ejecución con bajo overhead, eventos selectivos, callbacks y observabilidad segura.

    Ler mais

    Tempo de leitura: 6 minutos
    03/09/2026
    Desarrollador organizando datos con operator.attrgetter en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    operator.attrgetter: ordena objetos por atributos

    Aprende operator.attrgetter en Python para ordenar, agrupar y transformar objetos por atributos simples o anidados con código claro.

    Ler mais

    Tempo de leitura: 4 minutos
    02/09/2026
    Programación asíncrona con asyncio.Runner en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    asyncio.Runner: reutiliza el event loop con seguridad

    Aprende asyncio.Runner en Python para reutilizar el event loop, controlar contexto, señales, debug, cancelación y cierre asíncrono seguro.

    Ler mais

    Tempo de leitura: 7 minutos
    02/09/2026
    Compresión de datos binarios con Zstandard en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Zstandard con streams y diccionarios

    Aprende compression.zstd en Python para comprimir datos con Zstandard, streaming, diccionarios y límites seguros.

    Ler mais

    Tempo de leitura: 7 minutos
    01/09/2026
    Aplicación Python empaquetada como archivo ejecutable con zipapp
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    zipapp en Python: crea apps ejecutables

    Aprende zipapp en Python para empaquetar aplicaciones como archivos pyz ejecutables, incluir dependencias y distribuirlas con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    01/09/2026