31 · Clases base abstractas con abc
Declara un contrato que las subclases deben cumplir — si no implementan cada @abstractmethod, Python se niega a instanciarlas.
`from abc import ABC, abstractmethod` te permite declarar una **clase de contrato** que no puede instanciarse directamente. Todo método decorado con `@abstractmethod` **debe** ser sobreescrito por cada subclase concreta — Python lo impone en el momento de instanciación con un `TypeError`.
Sin esto:
Sin ABCs, una subclase que olvida implementar `.predict()` pasa silenciosamente hasta que el método faltante se llama en tiempo de ejecución — a menudo dentro de un bucle de entrenamiento. Los ABCs mueven el error al momento de instanciación, haciendo el contrato explícito y el bug inmediatamente visible.
abc.ABC (Abstract Base Class) es una clase base auxiliar que habilita el decorador @abstractmethod para imponer contratos. Cuando escribes class ModeloBase(ABC): y decoras métodos con @abstractmethod, Python marca esos métodos como requisitos. Cualquier intento de instanciar ModeloBase() directamente lanza TypeError: Can't instantiate abstract class. Las subclases que implementan todos los métodos abstractos pueden instanciarse normalmente.
Este patrón es la forma formal de definir una interfaz en Python — la diferencia con el duck typing es que las violaciones se detectan al crear el objeto en lugar de en la primera llamada al método faltante.
typing.Protocol (Python 3.8+) es la alternativa estructural: declaras las firmas de método esperadas sin requerir herencia. Los verificadores de tipos comprueban la conformidad estáticamente; sin imposición en tiempo de ejecución. Elige ABC cuando quieras imposición en tiempo de ejecución e implementación compartida (el ABC puede tener métodos concretos también — solo los decorados con @abstractmethod son obligatorios). Elige Protocol cuando quieras análisis estático amigable con el duck typing.
Python (in browser)
`BaseModel` tiene dos métodos abstractos (requisitos) y un método concreto (`score`) que las subclases heredan gratis. El `...` (elipsis) en los métodos abstractos es el cuerpo convencional — nunca se llama directamente.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
El mensaje de error nombra cada método abstracto no implementado — facilitando saber exactamente qué le falta a una subclase. Esto se dispara en el momento de construir `BaseModel()`, no más tarde cuando se habría llamado a `.fit()`.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
`MajorityClassifier` implementa tanto `fit` como `predict`, por lo que se instancia limpiamente. También hereda `.score()` de `BaseModel` gratis — ese es el patrón ABC: imponer el contrato, compartir utilidades gratis.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Con `Protocol`, el verificador de tipos comprueba la conformidad sin requerir `class MiModelo(ModelProtocol)`. Esto es **subtipado estructural** frente al **subtipado nominal** de ABC. Usa ABC cuando quieras código compartido + imposición en tiempo de ejecución; usa Protocol cuando integres con bibliotecas externas que no pueden heredar de tu ABC.
¿Puedes instanciar `BaseModel()` directamente si hereda de `ABC` y tiene métodos `@abstractmethod`?
- `class MiABC(ABC):` + `@abstractmethod` crea una clase de contrato. Python lanza `TypeError` en el momento de instanciación si falta algún método abstracto — el error nombra cada método no implementado.
- Los ABCs también pueden tener métodos concretos — utilidades compartidas que las subclases heredan gratis. Solo los métodos con `@abstractmethod` son requisitos.
- ABC = subtipado nominal + imposición en tiempo de ejecución + código compartido. `typing.Protocol` = subtipado estructural + solo imposición estática (no se requiere herencia).
El `BaseEstimator` de sklearn proporciona introspección de parámetros y clonación gratis a todo modelo que lo herede. `ClassifierMixin.score()` y `RegressorMixin.score()` son métodos concretos del ABC que proporcionan exactitud/R² automáticamente. El `nn.Module` de PyTorch lanza `NotImplementedError` desde `forward()` — un patrón informal de ABC. OpenAI Gym / Gymnasium define `Env` con `reset()` y `step()` abstractos que todo entorno debe implementar.
Si lo quitas: Sin ABCs, un `.predict()` faltante en un estimador compatible con sklearn pasa desapercibido hasta que un paso del pipeline lo llama — en lo profundo de un bucle de validación cruzada, lejos de la definición de clase. Los ABCs revelan este error inmediatamente al construir el objeto.