Resumen
El polimorfismo en Python se vuelve más claro y potente cuando se combina con typing y Protocol. Con contratos flexibles y sin herencia estricta, cualquier objeto que implemente los métodos requeridos puede participar, manteniendo la flexibilidad del duck typing y ganando ayuda de tipado estático en el editor.
¿Cómo potencia Protocol el polimorfismo en Python?
El polimorfismo permite que diferentes objetos respondan al mismo mensaje con resultados distintos: el método de solicitar libro funciona diferente si lo llama un estudiante o un profesor. Con Protocol, se define un contrato que exige la presencia de ese método en cualquier objeto que queramos usar en una colección común.
- Mismo mensaje, diferentes resultados al invocar solicitar libro.
- Interfaces sin herencia: basta con cumplir el contrato del Protocol.
- Tipado estático que ayuda: el editor alerta si un objeto no implementa el método requerido.
¿Qué papel cumple el duck typing?
Python aplica duck typing: si un objeto “camina y hace cuak como un pato”, se acepta. No importa la clase, solo que tenga los métodos necesarios. Protocol formaliza ese principio con contratos verificables por herramientas de tipos, sin perder flexibilidad.
¿Cómo definir un contrato con typing.Protocol?
Se importa Protocol desde typing para crear una clase que describe la interfaz mínima. Aquí, el contrato exige el método solicitar_libro con firma clara: recibe un título como str y retorna un str. El cuerpo usa ... para indicar que no hay implementación.
from typing import Protocol
class SolicitanteProtocol(Protocol):
def solicitar_libro(self, titulo: str) -> str:
"""Retorna el resultado de la solicitud de préstamo."""
...
- Hereda de typing.Protocol para declarar el contrato.
- Define la firma con tipos: título como str y retorno str.
- Usa elipsis (...) como cuerpo, solo describe la intención.
- Sirve para cualquier subclase o nuevo objeto “usuario” que deba solicitar libros.
¿Cómo obligar a implementar el método?
Al tipar colecciones, el editor valida que cada elemento cumpla el contrato. Si se intenta agregar un objeto que no define solicitar_libro, se marca como error de tipos.
class Libro:
def __init__(self, titulo: str, autor: str, isbn: str) -> None:
self.titulo = titulo
self.autor = autor
self.isbn = isbn
# Lista tipada: solo admite elementos que cumplan SolicitanteProtocol
usuarios: list[SolicitanteProtocol] = []
usuarios.append(Libro("Título de prueba", "Autor de prueba", "ISBN")) # error en el editor: no implementa solicitar_libro
¿Cómo usar una lista tipada e iterarla?
Se crea una lista de usuarios que cumplen el contrato y se itera. Cada elemento ejecuta su propia versión de solicitar_libro, aplicando polimorfismo “puro” y retornando resultados específicos.
class Estudiante:
def solicitar_libro(self, titulo: str) -> str:
return f"Préstamo autorizado para estudiante: {titulo}"
class Profesor:
def solicitar_libro(self, titulo: str) -> str:
return f"Préstamo autorizado para profesor: {titulo}"
usuarios: list[SolicitanteProtocol] = [Estudiante(), Profesor()]
for usuario in usuarios:
print(usuario.solicitar_libro("Título de prueba"))
- Se ejecuta la versión adecuada de solicitar_libro según el objeto.
- Se imprime el resultado del préstamo para cada usuario.
- Si se agrega un objeto sin el método, el editor lo marca como incompatible con el Protocol.
¿Qué reto práctico puedes implementar ya?
Define un Protocol para libros y crea dos implementaciones con su propia lógica de préstamo. La idea: contratos claros, implementaciones independientes, lista tipada y polimorfismo en acción.
from typing import Protocol
class LibroProtocol(Protocol):
def prestar(self): ...
def calcular_duracion(self): ...
class LibroFisico:
def prestar(self): ...
def calcular_duracion(self): ...
class LibroElectronico:
def prestar(self): ...
def calcular_duracion(self): ...
biblioteca: list[LibroProtocol] = [LibroFisico(), LibroElectronico()]
for libro in biblioteca:
# Usa la misma interfaz con comportamientos distintos
print(libro.prestar(), libro.calcular_duracion())
¿Te gustaría compartir cómo aplicarías Protocol en tus modelos de dominio o qué métodos incluirías en tu contrato de libro? Deja tus ideas y preguntas en los comentarios.