0Pricing
Python Academy · Lección

TypeVar, clases genéricas y Protocol

Defina tipos genéricos reutilizables y subtipado estructural con Protocol.

TypeVar, clases genéricas y Protocol es una lección gratuita de Python Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Python Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Python Academy incluye 4 lecciones en total.

¿Qué es TypeVar?

TypeVar declara una variable de tipo, un marcador de posición que puede representar cualquier tipo y que, si es necesario, puede estar restringido. Se usa en funciones y clases genéricas.

from typing import TypeVar

T = TypeVar("T")

def identity(value: T) -> T:
    return value

print(identity(42))      # int
print(identity("hello")) # str

Funciones genéricas

Una función que usa TypeVar tanto en los tipos de los parámetros como en el tipo devuelto permite que mypy infiera el tipo devuelto a partir del tipo del argumento.

from typing import TypeVar

T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]

x: int = first([1, 2, 3])     # mypy knows x is int
s: str = first(["a","b","c"]) # mypy knows s is str

TypeVar restringido

Pase restricciones de tipo a TypeVar para limitar los tipos que se aceptan.

from typing import TypeVar

Numeric = TypeVar("Numeric", int, float)

def double(n: Numeric) -> Numeric:
    return n * 2

print(double(5))    # 10
print(double(2.5))  # 5.0
# double("x")  # mypy error

Clases genéricas

Herede de Generic[T] para crear una clase parametrizada mediante una variable de tipo.

from typing import Generic, TypeVar

T = TypeVar("T")

class Stack(Generic[T]):
    def __init__(self) -> None:
        self._items: list[T] = []

    def push(self, item: T) -> None:
        self._items.append(item)

    def pop(self) -> T:
        return self._items.pop()

stack: Stack[int] = Stack()
stack.push(1)
print(stack.pop())   # 1

Varios TypeVar

Use varios TypeVar para parametrizar una clase o función con dos tipos independientes.

from typing import Generic, TypeVar

K = TypeVar("K")
V = TypeVar("V")

class Pair(Generic[K, V]):
    def __init__(self, key: K, value: V) -> None:
        self.key = key
        self.value = value

p: Pair[str, int] = Pair("age", 30)
print(p.key, p.value)   # age 30

Protocol — Subtipado estructural

Protocol define una interfaz mediante los métodos y atributos que debe tener una clase, sin exigir una herencia explícita («duck typing, con comprobación de tipos»).

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None: ...

def render(obj: Drawable) -> None:
    obj.draw()

class Circle:
    def draw(self) -> None:
        print("Drawing circle")

render(Circle())   # works — Circle satisfies Drawable

Protocol con runtime_checkable

Añada @runtime_checkable a un Protocol para habilitar las comprobaciones isinstance() durante la ejecución.

from typing import Protocol, runtime_checkable

@runtime_checkable
class Closeable(Protocol):
    def close(self) -> None: ...

class File:
    def close(self) -> None: print("closed")

print(isinstance(File(), Closeable))   # True

Protocol frente a ABC

Las ABC requieren herencia explícita (class Dog(Animal)). Los Protocol funcionan mediante coincidencia estructural: si una clase tiene los métodos correctos, satisface el protocolo independientemente de la herencia.

from typing import Protocol
from abc import ABC, abstractmethod

# ABC: nominal typing
class Printable(ABC):
    @abstractmethod
    def display(self) -> None: ...

# Protocol: structural typing
class Displayable(Protocol):
    def display(self) -> None: ...

TypeVar con bound

TypeVar("T", bound=BaseClass) restringe T a BaseClass o a cualquiera de sus subclases.

from typing import TypeVar

class Animal:
    def speak(self) -> str: return "..."

A = TypeVar("A", bound=Animal)

def make_speak(animal: A) -> str:
    return animal.speak()

Alias genérico — Python 3.12

Python 3.12 introduce la instrucción type para crear alias de tipos de forma clara y la sintaxis class Foo[T] para los genéricos sin importar TypeVar.

# Python 3.12+
type Vector = list[float]
type Matrix = list[Vector]

class Stack[T]:
    def __init__(self) -> None: self._items: list[T] = []
    def push(self, item: T) -> None: self._items.append(item)
    def pop(self) -> T: return self._items.pop()

Tipo Self

Self (de typing en Python 3.11 o posterior) anota los métodos que devuelven la clase actual, algo útil en interfaces fluidas y subclases.

from typing import Self

class Builder:
    def __init__(self) -> None:
        self.parts: list[str] = []

    def add(self, part: str) -> Self:
        self.parts.append(part)
        return self

b = Builder().add("a").add("b")
print(b.parts)   # ["a", "b"]

Comprobación rápida

¿Cuál es la diferencia fundamental entre un Protocol y una ABC en el tipado de Python?

Repaso

TypeVar crea marcadores de posición de tipos para funciones y clases genéricas. Generic[T] parametriza las clases. Protocol permite el subtipado estructural sin herencia. Use bound= o restricciones de tipo en TypeVar para limitar los tipos aceptados.

Preguntas frecuentes

¿La lección «TypeVar, clases genéricas y Protocol» es gratis?

Sí — el texto completo de «TypeVar, clases genéricas y Protocol» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Python Academy, actualiza a CoddyKit PRO. El curso de Python Academy incluye 4 lecciones en total.

¿Qué aprenderé en «TypeVar, clases genéricas y Protocol»?

Defina tipos genéricos reutilizables y subtipado estructural con Protocol. Practicas Python Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Python Academy?

No se requiere experiencia previa. Python Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «TypeVar, clases genéricas y Protocol»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Python Academy?

Sí. Cada lección de Python Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Anotaciones de tipos básicas
  2. Tipos complejos: List, Dict, Optional y Union
  3. TypeVar, clases genéricas y Protocol
  4. Ejecución de mypy y corrección de errores de tipos
← Volver a Python Academy