Genéricos Integrados y de Colección
El Python moderno utiliza genéricos de colección integrados (list[int]) y tipos abstractos de collections.abc para describir contenedores con precisión, tanto para los lectores como para mypy/pyright.
Receta
from collections.abc import Iterable, Mapping, Sequence
def total_lengths(names: Sequence[str]) -> int:
return sum(len(n) for n in names)
def merge(base: Mapping[str, int], extra: Mapping[str, int]) -> dict[str, int]:
return {**base, **extra}Cuándo usar esto:
- Parámetros de funciones públicas que aceptan cualquier secuencia
- APIs de
dictde solo lectura sin mutación - Tipado de estructuras anidadas similares a JSON
- Utilidades que consumen iteradores
Ejemplo de Trabajo
from collections.abc import Callable, Iterable, Iterator, Mapping
def index_by(items: Iterable[dict], key: str) -> dict[str, dict]:
result: dict[str, dict] = {}
for item in items:
result[str(item[key])] = item
return result
def batch(iterator: Iterator[int], size: int) -> Iterable[list[int]]:
batch_items: list[int] = []
for value in iterator:
batch_items.append(value)
if len(batch_items) == size:
yield batch_items
batch_items = []
if batch_items:
yield batch_items
def apply_all(fns: Mapping[str, Callable[[], None]]) -> None:
for fn in fns.values():
fn()
if __name__ == "__main__":
rows = [{"id": "1", "name": "Ada"}, {"id": "2", "name": "Linus"}]
print(index_by(rows, "id"))Lo que esto demuestra:
Iterableacepta listas, generadores e iteradores personalizadosIteratores de un solo paso; el verificador advierte si se reutiliza incorrectamente en modo estrictoMappingdocumenta diccionarios de solo lectura sin métodos de mutaciónCallable[[], None]tipa funciones de efectos secundarios sin argumentos
Inmersión Profunda
Cómo Funciona
- PEP 585 - Genéricos integrados en 3.9+ (
list[int]). - Varianza - La mayoría de los genéricos de contenedores son invariantes (
list[Dog]nolist[Animal]). - collections.abc - Verificaciones
isinstanceen tiempo de ejecución y objetivos de tipado estructural. - typing vs collections.abc - Prefiera
collections.abcen anotaciones (3.9+). - Genéricos anidados -
dict[str, list[int]]para listas de adyacencia.
Opciones Comunes de ABC
| Aceptar | Cuándo |
|---|---|
Sequence | Se necesita indexación + len |
Iterable | Un solo pase hacia adelante |
Mapping | Búsqueda de claves de solo lectura |
MutableMapping | Necesita setitem/delitem |
Notas de Python
# lista invariante - usar Sequence para parámetro de solo lectura
def print_all(items: Sequence[str]) -> None:
for item in items:
print(item)Trampas Comunes
- list vs List -
typing.Listestilo obsoleto en 3.9+. Solución:list[int]. - Iterable consumido dos veces - La pista de tipo no detiene el error de doble iteración. Solución: Documentar o requerir
Sequence. - Claves de dict invariantes -
dict[str, int]no es compatible condict[str, float]en varianza estricta. Solución: Usar unión de valores oMapping. - Any en tipo interno -
dict[str, Any]pierde seguridad. Solución:TypedDicto modelo Pydantic. - tupla de longitud variable -
tuple[int, ...]para longitud variable homogénea frente atuple[int, str]fija.
Alternativas
| Alternativa | Usar Cuándo | No Usar Cuándo |
|---|---|---|
TypedDict | Claves de cadena conocidas | Solo claves dinámicas |
| Modelo Pydantic | JSON anidado validado | Núcleo numérico interno |
TypeAlias | Alias anidado complejo | Lista simple list[int] |
numpy.ndarray | Tensores numéricos | Contenedores generales de Python |
Preguntas Frecuentes
¿Sequence vs list?
Parámetro de tipo Sequence cuando solo lee/indexa; list cuando el llamador debe pasar específicamente una lista mutable.
¿Iterable vs Iterator?
Iterable produce un iterador a través de iter(). Iterator se agota después de un pase.
¿Mapping vs dict?
Mapping indica una API de solo lectura; dict cuando la función muta o devuelve un dict concreto.
¿Genéricos de set?
set[str] para conjuntos homogéneos - invariante como list.
¿Tipado de frozenset?
frozenset[str] igual que set para propósitos de tipado.
¿Tipo de retorno de generador?
Iterator[T] o Iterable[T] - Iterator tiene semántica de un solo pase más estricta.
¿bytes y memoryview?
bytes para binario; memoryview raramente en APIs públicas - usar tipos del protocolo Buffer en tipado avanzado.
¿dict JSON anidado?
dict[str, object] es laxo; TypedDict o modelos para seguridad real.
¿callable vs Callable?
collections.abc.Callable es preferido en anotaciones 3.9+.
¿lista de solo lectura?
Sequence[T] - no hay append en el contrato de tipo, aunque la lista en tiempo de ejecución sigue siendo mutable.
Relacionado
- Conceptos Básicos de Pistas de Tipo - introducción
- TypedDict & NamedTuple - diccionarios estructurados
- Optional, Union y el Operador | - uniones en contenedores
- Genéricos y TypeVar - tipos paramétricos
Versiones de la Pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.