Contenido del curso

Fundamentos de Programación y Python

Programación Orientada a Objetos en Python

`__new__` vs `__init__` en Python

Resumen

La metaprogramación en Python te permite controlar cómo se crean y configuran tus objetos antes incluso de que existan. Si ya usaste __init__ para construir atributos en programación orientada a objetos, ahora toca dar el siguiente paso: entender cómo __new__ entra en escena para tomar el control de la instancia desde su origen.

Qué hace el método new frente al init

Cuando creas una clase en Python, hay dos métodos especiales que trabajan en cadena. Uno construye la instancia, el otro la inicializa. Y el orden importa.

El método __new__ es el responsable de crear una nueva instancia del objeto. Se ejecuta antes que __init__ y devuelve el objeto recién nacido. Después entra __init__, que recibe esa instancia y le asigna los atributos que tú definiste, como un factor de multiplicación o cualquier otro dato que necesite tu clase.

¿Qué diferencia hay entre new e init? __new__ crea la instancia y devuelve el objeto. __init__ recibe esa instancia ya creada y la inicializa con valores. Primero se ejecuta __new__, luego __init__.

Por qué new va antes que init en el código

Aunque __init__ sea el método que más conoces, cuando trabajas con __new__ la lógica de lectura cambia. Por buenas prácticas, __new__ se escribe al inicio de la clase porque ahí es donde nace la instancia. Solo después tiene sentido inicializarla.

Dentro de __new__ debes invocar a super() para que la clase padre genere el objeto base. Sin esa llamada, no hay instancia que devolver.

Cómo construir una clase generadora de multiplicadores

Imagina una clase que recibe un factor y multiplica cualquier número que le pases. Es un caso simple pero ideal para ver los dos métodos en acción.

El flujo es así:

  1. Defines __new__ para crear la instancia y dejar un mensaje tipo Creando instancia con factor 5.
  2. Defines __init__ para guardar el factor como atributo y mostrar Inicializando valor con factor igual a 5.
  3. Creas un método que reciba un número y lo multiplique por el factor almacenado.

Cuando ejecutas multiplier = GeneradorMultiplicadores(5), el número 5 viaja primero a __new__ y luego a __init__. Si después llamas al método con el valor 10, obtienes 50 como resultado.

python class GeneradorMultiplicadores: def new(cls, factor): print(f"Creando instancia con factor {factor}") instancia = super().new(cls) return instancia

def __init__(self, factor): print(f"Inicializando valor con factor igual a {factor}") self.factor = factor def multiplicar(self, numero): return self.factor * numero

multiplier = GeneradorMultiplicadores(5) resultado = multiplier.multiplicar(10) print(resultado)

Qué imprime la consola al ejecutar el código

Verás tres salidas en orden. Primero el mensaje desde __new__ confirmando la creación. Luego el mensaje desde __init__ confirmando la inicialización. Y al final, el resultado de la multiplicación: 50.

Ese rastro en consola es útil cuando depuras o necesitas auditar cómo se están construyendo tus objetos en proyectos grandes.

Cuándo conviene usar metaprogramación en tus proyectos

Aquí viene lo interesante: no todas las clases necesitan __new__. La mayoría del tiempo, con __init__ te basta y te sobra.

La metaprogramación cobra sentido cuando trabajas en proyectos complejos donde necesitas controlar la creación de cada instancia, validar datos antes de construir el objeto, implementar patrones como singleton, o personalizar el comportamiento de clases que heredan de otras.

¿Siempre debo usar new al crear una clase? No. Úsalo solo cuando necesites controlar la creación misma del objeto, no su inicialización. Para casos comunes, __init__ es suficiente.

Usar metaprogramación sin necesidad agrega complejidad innecesaria a tu código. Evalúa el proyecto antes de decidir: si lo que necesitas es solo asignar atributos, quédate con el constructor clásico. Si requieres flexibilidad y control desde la creación misma, ahí es donde __new__ brilla.

¿En qué tipo de proyecto crees que tendría más sentido aplicar __new__? Cuéntame en los comentarios cómo lo usarías.