collections.UserList es una clase auxiliar para crear secuencias mutables personalizadas. Guarda los elementos en una lista normal disponible mediante data y ofrece una superficie predecible para validación, normalización, logging y reglas de dominio.
Es útil cuando una colección debe comportarse como lista, pero necesita controlar inserciones, reemplazos, borrado, tipos aceptados u operaciones por lotes.
Ejemplo básico
from collections import UserList
class ListaEnteros(UserList):
def _validar(self, valor):
if not isinstance(valor, int):
raise TypeError("solo enteros")
return valor
def append(self, valor):
super().append(self._validar(valor))
def insert(self, indice, valor):
super().insert(indice, self._validar(valor))
Validar solo append no es suficiente. La lista también cambia mediante asignación por índice, slices, extend y +=.
Cubrir todas las mutaciones
class ListaEnteros(UserList):
def _validar(self, valor):
if not isinstance(valor, int):
raise TypeError("solo enteros")
return valor
def __setitem__(self, indice, valor):
if isinstance(indice, slice):
valor = [self._validar(item) for item in valor]
else:
valor = self._validar(valor)
super().__setitem__(indice, valor)
def append(self, valor):
super().append(self._validar(valor))
def insert(self, indice, valor):
super().insert(indice, self._validar(valor))
def extend(self, valores):
super().extend(self._validar(item) for item in valores)
El atributo data
data contiene la lista real. Modificarla directamente puede saltarse validaciones, por lo que conviene tratarla como un detalle interno.
Normalizar valores
class Etiquetas(UserList):
def _normalizar(self, valor):
texto = str(valor).strip().casefold()
if not texto:
raise ValueError("etiqueta vacía")
return texto
Decide si se permiten duplicados. Si la unicidad es la regla principal, un set o mapping puede representar mejor el dominio.
UserList frente a heredar de list
Una subclase directa de list puede ser más rápida y necesaria cuando una API exige el tipo concreto. UserList prioriza extensibilidad y dirige las operaciones por métodos más sencillos de personalizar.
UserList frente a MutableSequence
Implementa MutableSequence cuando los datos no viven en una lista normal, por ejemplo una secuencia en disco, una ventana virtual o una estructura compacta. Usa UserList cuando una lista interna sea suficiente.
Operaciones que crean nuevas secuencias
Prueba concatenación, multiplicación, slicing y copia. Define si el resultado debe conservar la clase personalizada o convertirse en una lista normal.
Ordenación e instrumentación
class Tareas(UserList):
def sort(self, *, key=None, reverse=False):
registrar("ordenando tareas")
super().sort(key=key, reverse=reverse)
Evita efectos secundarios costosos o sorprendentes en operaciones familiares.
Serialización
Algunos serializadores requieren una lista concreta. Convierte explícitamente:
import json
json.dumps(list(valores), ensure_ascii=False)
Errores comunes
- Validar solo
append. - Ignorar asignación por slice y
extend. - Modificar
datadirectamente. - Usar una lista cuando se necesita unicidad.
- Suponer el tipo retornado por slicing o concatenación.
Buenas prácticas
Enumera todos los caminos de mutación, centraliza validación, usa super(), prueba operadores y documenta los tipos de retorno. Consulta las guías internas de listas en Python y collections.
Conclusión
UserList es una base práctica para secuencias personalizadas respaldadas por una lista común. Facilita invariantes coherentes sin depender de detalles internos de list.







