Metaclases en Python: guía completa y ejemplos prácticos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Los metaclases en Python son clases especiales que crean y gestionan otras clases. Como en Python todo es un objeto, incluidas las clases, los metaclases pueden considerarse "clases para clases". Proporcionan un mecanismo para controlar el proceso de creación de clases y modificar su comportamiento en el momento de la definición.

Cómo funcionan los metaclases

Cuando Python encuentra la definición de una clase, automáticamente usa el metaclase type para crearla. El proceso es el siguiente:

class MiClase:
    pass

Internamente, Python ejecuta:

MiClase = type('MiClase', (), {})

Donde:

  • 'MiClase' — el nombre de la clase
  • () — la tupla de clases padre
  • {} — el diccionario de atributos y métodos de la clase

El metaclase incorporado type es el responsable de crear todas las clases en Python por defecto.

Crear tus propios metaclases

Los metaclases personalizados se crean heredando de type y sobrescribiendo sus métodos:

class MiMeta(type):
    def __new__(cls, name, bases, attrs):
        print(f"Creando la clase {name}")
        attrs['creado_por_metaclase'] = True
        return super().__new__(cls, name, bases, attrs)

class MiClase(metaclass=MiMeta):
    pass

print(MiClase.creado_por_metaclase)  # True

Métodos clave de los metaclases

__new__

Controla la creación de la clase. Se llama antes de __init__ y devuelve la nueva clase:

class MetaCreacion(type):
    def __new__(cls, name, bases, attrs):
        # Modificación de atributos antes de crear la clase
        attrs['id_clase'] = id(cls)
        return super().__new__(cls, name, bases, attrs)

__init__

Inicializa la clase ya creada:

class MetaInit(type):
    def __init__(cls, name, bases, attrs):
        print(f"Inicializando la clase {name}")
        super().__init__(name, bases, attrs)

__call__

Define el comportamiento al crear instancias de la clase:

class MetaCall(type):
    def __call__(cls, *args, **kwargs):
        print(f"Creando instancia de {cls.__name__}")
        return super().__call__(*args, **kwargs)

Ejemplos prácticos de uso

Conversión automática de atributos

class MetaMayusculas(type):
    def __new__(cls, name, bases, attrs):
        attrs_mayus = {}
        for attr_name, attr_value in attrs.items():
            if not attr_name.startswith('__'):
                attrs_mayus[attr_name.upper()] = attr_value
            else:
                attrs_mayus[attr_name] = attr_value
        return super().__new__(cls, name, bases, attrs_mayus)

class MiClase(metaclass=MetaMayusculas):
    attr1 = 'valor1'
    attr2 = 'valor2'

print(hasattr(MiClase, 'ATTR1'))  # True
print(hasattr(MiClase, 'attr1'))  # False

Implementación del patrón Singleton

class MetaSingleton(type):
    _instancias = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instancias:
            cls._instancias[cls] = super().__call__(*args, **kwargs)
        return cls._instancias[cls]

class ConexionBD(metaclass=MetaSingleton):
    def __init__(self):
        print("Creando conexión a la base de datos")

db1 = ConexionBD()
db2 = ConexionBD()
print(db1 is db2)  # True

Validación de la estructura de clases

class MetaValidado(type):
    def __new__(cls, na                

Blogs

Book Recommendations