PythonAprende PythonDocumentación

stdlib avanzada: collections

Counter, defaultdict, deque y las herramientas ocultas de Python.

El módulo collections guarda estructuras de datos especializadas que resuelven problemas diarios con menos código y mejor rendimiento. Son el equipo secreto de los Pythonistas experimentados.

Counter: contar sin escribir el bucle

from collections import Counter

palabras = ["python", "es", "genial", "python", "es", "python"]

conteo = Counter(palabras)
print(conteo)                    # Counter({'python': 3, 'es': 2, 'genial': 1})

print(conteo.most_common(2))     # [('python', 3), ('es', 2)] → top 2

print(Counter("mississippi"))    # también cuenta caracteres

Todo el patrón "diccionario de conteo" de la lección de diccionarios, en una línea.

defaultdict: dicts con valor por defecto

from collections import defaultdict

grupos = defaultdict(list)       # valor por defecto: lista nueva

personas = [("Ana", "bogota"), ("Luis", "bogota"), ("Sofia", "medellin")]

for nombre, ciudad in personas:
    grupos[ciudad].append(nombre)   # ¡sin verificar si la clave existe!

print(grupos)   # defaultdict(<class 'list'>, {'bogota': ['Ana', 'Luis'], 'medellin': ['Sofia']})

Al acceder a una clave inexistente, defaultdict la crea con el valor por defecto. Desaparece el if ciudad not in grupos: de siempre. Otros defaults útiles: defaultdict(int) para contadores, defaultdict(set) para agrupar sin duplicados.

deque: la cola eficiente

from collections import deque

historial = deque(maxlen=3)      # cola con límite: descarta lo viejo

for accion in ["abrir", "editar", "guardar", "cerrar"]:
    historial.append(accion)
    print(list(historial))
# ['abrir']
# ['abrir', 'editar']
# ['abrir', 'editar', 'guardar']
# ['editar', 'guardar', 'cerrar']  ← el más viejo salió solo

¿Por qué no una lista normal? lista.pop(0) es O(n) — desplaza todos los elementos. En deque, popleft() y appendleft() son O(1): constantes.

cola = deque(["tarea1", "tarea2"])
cola.append("tarea3")     # entra por la derecha
siguiente = cola.popleft()  # sale por la izquierda → cola FIFO real

Perfecto para: colas de tareas, historiales con límite, algoritmos BFS.

namedtuple: tuplas con nombre

from collections import namedtuple

Punto = namedtuple("Punto", ["x", "y"])
p = Punto(3, 5)

print(p.x, p.y)    # 3 5 → por NOMBRE, no por índice
print(p[0])        # 3 → sigue siendo una tupla

La legibilidad de un objeto con la memoria y ligereza de una tupla. (En código moderno mira también dataclasses de la lección intermedia.)

Otras perlas de la stdlib

import heapq
prioridades = [5, 1, 3]
heapq.heapify(prioridades)
print(heapq.heappop(prioridades))   # 1 → el menor siempre arriba

from statistics import mean, median
print(mean([2, 4, 6]))    # 4.0

heapq para colas de prioridad, statistics para lo básico sin numpy, bisect para listas ordenadas.

Resumen

  • Counter cuenta y ordena por frecuencia en una línea
  • defaultdict elimina los "¿existe la clave?" de tus bucles
  • deque para colas FIFO/limitadas: O(1) en ambos extremos
  • namedtuple da nombres a tuplas de posición
  • Conocer la stdlib es la forma más barata de escribir menos código

Quiz

  1. 1. ¿Qué devuelve Counter("banana").most_common(1)?

  2. 2. ¿Qué ventaja tiene defaultdict(list) sobre un dict normal?

  3. 3. ¿Por qué usar deque para colas en vez de una lista?

Ejercicios

Ejercicio 1: Top frecuencias

Usa collections.Counter para imprimir las 2 palabras más frecuentes de la lista. Resultado: [('python', 3), ('es', 2)]

Cargando editor…

Ejercicio 2: Agrupar con defaultdict

Usa defaultdict(list) para agrupar personas por ciudad e imprime el dict ordenado por clave. Resultado: {'bogota': ['Ana', 'Luis'], 'medellin': ['Sofia']}

Cargando editor…