28 · Herencia y super()
Construye jerarquías de clases con class Hijo(Padre), llama código del padre con super(), entiende el MRO y aprende cuándo preferir composición sobre herencia profunda.
`class Hijo(Padre):` significa "Hijo **es un** Padre, más algo extra". El hijo hereda cada método y atributo del padre. `super().__init__(...)` delega al `__init__` del padre para no duplicar el código de inicialización. Python resuelve la búsqueda de métodos a través del **Method Resolution Order (MRO)** — una búsqueda en profundidad de izquierda a derecha que maneja correctamente la herencia múltiple.
Sin esto:
Sin herencia copiarías `.fit()` y `.predict()` en cada clase de estimador. Toda la taxonomía de sklearn — `BaseEstimator`, `ClassifierMixin`, `RegressorMixin` — depende de la herencia para compartir docenas de métodos utilitarios entre cientos de modelos.
La herencia permite que una clase reutilice y extienda el comportamiento de otra. La clase padre (base) contiene la implementación compartida; cada clase hijo (derivada) la hereda y puede sobreescribir métodos — reemplazando la versión del padre definiendo un método con el mismo nombre.
super() te da un proxy a la clase padre. Llamar super().__init__(...) dentro del __init__ de un hijo ejecuta el inicializador del padre para no duplicar el código de inicialización. También puedes llamar super().nombre_metodo(...) para ejecutar la versión del padre de cualquier método sobreescrito — útil cuando quieres extender en lugar de reemplazar comportamiento.
La herencia múltiple (class D(B, C):) está permitida en Python. Cuando el mismo nombre de método aparece en varios padres, Python usa el algoritmo de linealización C3 para construir un MRO (Method Resolution Order) determinista. NombreClase.__mro__ o help(NombreClase) te muestra la cadena de resolución completa — vale la pena comprobar cuando ves un binding de método inesperado. El consejo general: favorecer la composición (un modelo TIENE-UN escalador) sobre jerarquías de herencia profundas (un modelo ES-UN escalador ES-UN estimador ES-UN ...) — las jerarquías profundas son difíciles de entender y depurar.
Python (in browser)
`super().__init__(nombre)` y `super().fit(X, y)` son los dos usos más comunes de `super()`. Sin `super().__init__()`, el `__init__` del hijo tendría que duplicar toda la configuración de atributos del padre — y cualquier cambio futuro al `__init__` del padre tendría que reflejarse manualmente.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
El MRO de `D` es `[D, B, C, A, object]`. Cuando `B.hello` llama a `super().hello()`, Python busca en el MRO desde la posición de `B` — la siguiente clase es `C`, no `A`. Por eso el diamante produce `"B -> C -> A"` y no `"B -> A"`. Entender el MRO previene los misteriosos bugs de "se llamó al método equivocado" en jerarquías multi-herencia.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Todo modelo de PyTorch hereda de `nn.Module`. La llamada `super().__init__()` es obligatoria — conecta el registro interno de parámetros que rastrea gradientes. Sobreescribes `forward()` (el padre lo declara pero espera que lo reemplaces) y llamas al modelo como función: `output = model(x)` invoca `__call__`, que envuelve `forward`.
¿Qué hace `super().__init__()` dentro del `__init__` de una clase hija?
- `class Hijo(Padre):` hereda todo de `Padre`. Sobreescribe un método redefiniéndolo; llama a la versión del padre con `super().nombre_metodo(...)`.
- `super().__init__(...)` ejecuta el `__init__` del padre sobre la instancia actual — llámalo siempre primero en el `__init__` del hijo a menos que tengas una razón deliberada para no hacerlo.
- El MRO de Python (`NombreClase.__mro__`) define el orden de resolución de métodos en herencia múltiple. Prefiere composición sobre jerarquías de herencia profundas en código ML de producción.
Todo modelo de PyTorch hereda de `nn.Module` — `super().__init__()` es la primera línea de todo `__init__`. Sklearn usa `BaseEstimator` más clases mixin (`ClassifierMixin`, `RegressorMixin`) para inyectar `get_params`, `set_params`, `score` y otras utilidades mediante herencia múltiple. LightGBM y XGBoost envuelven sus modelos C++ en clases Python que heredan de `BaseEstimator` para que encajen en pipelines de sklearn sin modificación.
Si lo quitas: Sin herencia, cada modelo reimplementaría `get_params`, `set_params`, `clone` y `score` desde cero — miles de líneas de código utilitario duplicado solo en el ecosistema de sklearn.